Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: third_party/harfbuzz-ng/src/hb-ot-shape.cc

Issue 10915172: harfbuzz-ng roll (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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,2012 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
11 * all copies of this software. 11 * all copies of this software.
12 * 12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 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 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE. 17 * DAMAGE.
18 * 18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
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 #define HB_SHAPER ot
30 #define hb_ot_shaper_face_data_t hb_ot_layout_t
31 #define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
32 #include "hb-shaper-impl-private.hh"
33
29 #include "hb-ot-shape-private.hh" 34 #include "hb-ot-shape-private.hh"
35 #include "hb-ot-shape-complex-private.hh"
36 #include "hb-ot-shape-fallback-private.hh"
30 #include "hb-ot-shape-normalize-private.hh" 37 #include "hb-ot-shape-normalize-private.hh"
31 38
32 #include "hb-font-private.hh" 39 #include "hb-ot-layout-private.hh"
33 #include "hb-set-private.hh" 40 #include "hb-set-private.hh"
34 41
35 42
36 43 static hb_tag_t common_features[] = {
37 hb_tag_t common_features[] = {
38 HB_TAG('c','c','m','p'), 44 HB_TAG('c','c','m','p'),
39 HB_TAG('l','i','g','a'), 45 HB_TAG('l','i','g','a'),
40 HB_TAG('l','o','c','l'), 46 HB_TAG('l','o','c','l'),
41 HB_TAG('m','a','r','k'), 47 HB_TAG('m','a','r','k'),
42 HB_TAG('m','k','m','k'), 48 HB_TAG('m','k','m','k'),
43 HB_TAG('r','l','i','g'), 49 HB_TAG('r','l','i','g'),
44 }; 50 };
45 51
46 52
47 hb_tag_t horizontal_features[] = { 53 static hb_tag_t horizontal_features[] = {
48 HB_TAG('c','a','l','t'), 54 HB_TAG('c','a','l','t'),
49 HB_TAG('c','l','i','g'), 55 HB_TAG('c','l','i','g'),
50 HB_TAG('c','u','r','s'), 56 HB_TAG('c','u','r','s'),
51 HB_TAG('k','e','r','n'), 57 HB_TAG('k','e','r','n'),
58 HB_TAG('r','c','l','t'),
52 }; 59 };
53 60
54 /* Note: 61 /* Note:
55 * Technically speaking, vrt2 and vert are mutually exclusive. 62 * Technically speaking, vrt2 and vert are mutually exclusive.
56 * According to the spec, valt and vpal are also mutually exclusive. 63 * According to the spec, valt and vpal are also mutually exclusive.
57 * But we apply them all for now. 64 * But we apply them all for now.
58 */ 65 */
59 hb_tag_t vertical_features[] = { 66 static hb_tag_t vertical_features[] = {
60 HB_TAG('v','a','l','t'), 67 HB_TAG('v','a','l','t'),
61 HB_TAG('v','e','r','t'), 68 HB_TAG('v','e','r','t'),
62 HB_TAG('v','k','r','n'), 69 HB_TAG('v','k','r','n'),
63 HB_TAG('v','p','a','l'), 70 HB_TAG('v','p','a','l'),
64 HB_TAG('v','r','t','2'), 71 HB_TAG('v','r','t','2'),
65 }; 72 };
66 73
67 74
68 75
69 struct hb_ot_shape_planner_t
70 {
71 hb_ot_map_builder_t map;
72 hb_ot_complex_shaper_t shaper;
73
74 hb_ot_shape_planner_t (void) : map () {}
75 ~hb_ot_shape_planner_t (void) { map.finish (); }
76
77 inline void compile (hb_face_t *face,
78 const hb_segment_properties_t *props,
79 struct hb_ot_shape_plan_t &plan)
80 {
81 plan.shaper = shaper;
82 map.compile (face, props, plan.map);
83 }
84
85 private:
86 NO_COPY (hb_ot_shape_planner_t);
87 };
88
89 static void 76 static void
90 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, 77 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
91 const hb_segment_properties_t *props, 78 const hb_segment_properties_t *props,
92 const hb_feature_t *user_features, 79 const hb_feature_t *user_features,
93 unsigned int num_user_features) 80 unsigned int num_user_features)
94 { 81 {
82 hb_ot_map_builder_t *map = &planner->map;
83
95 switch (props->direction) { 84 switch (props->direction) {
96 case HB_DIRECTION_LTR: 85 case HB_DIRECTION_LTR:
97 planner->map.add_bool_feature (HB_TAG ('l','t','r','a')); 86 map->add_bool_feature (HB_TAG ('l','t','r','a'));
98 planner->map.add_bool_feature (HB_TAG ('l','t','r','m')); 87 map->add_bool_feature (HB_TAG ('l','t','r','m'));
99 break; 88 break;
100 case HB_DIRECTION_RTL: 89 case HB_DIRECTION_RTL:
101 planner->map.add_bool_feature (HB_TAG ('r','t','l','a')); 90 map->add_bool_feature (HB_TAG ('r','t','l','a'));
102 planner->map.add_bool_feature (HB_TAG ('r','t','l','m'), false); 91 map->add_bool_feature (HB_TAG ('r','t','l','m'), false);
103 break; 92 break;
104 case HB_DIRECTION_TTB: 93 case HB_DIRECTION_TTB:
105 case HB_DIRECTION_BTT: 94 case HB_DIRECTION_BTT:
106 case HB_DIRECTION_INVALID: 95 case HB_DIRECTION_INVALID:
107 default: 96 default:
108 break; 97 break;
109 } 98 }
110 99
111 #define ADD_FEATURES(array) \ 100 #define ADD_FEATURES(array) \
112 HB_STMT_START { \ 101 HB_STMT_START { \
113 for (unsigned int i = 0; i < ARRAY_LENGTH (array); i++) \ 102 for (unsigned int i = 0; i < ARRAY_LENGTH (array); i++) \
114 planner->map.add_bool_feature (array[i]); \ 103 map->add_bool_feature (array[i]); \
115 } HB_STMT_END 104 } HB_STMT_END
116 105
117 hb_ot_shape_complex_collect_features (planner->shaper, &planner->map, props); 106 if (planner->shaper->collect_features)
107 planner->shaper->collect_features (planner);
118 108
119 ADD_FEATURES (common_features); 109 ADD_FEATURES (common_features);
120 110
121 if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) 111 if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
122 ADD_FEATURES (horizontal_features); 112 ADD_FEATURES (horizontal_features);
123 else 113 else
124 ADD_FEATURES (vertical_features); 114 ADD_FEATURES (vertical_features);
125 115
116 if (planner->shaper->override_features)
117 planner->shaper->override_features (planner);
118
126 #undef ADD_FEATURES 119 #undef ADD_FEATURES
127 120
128 for (unsigned int i = 0; i < num_user_features; i++) { 121 for (unsigned int i = 0; i < num_user_features; i++) {
129 const hb_feature_t *feature = &user_features[i]; 122 const hb_feature_t *feature = &user_features[i];
130 planner->map.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1)); 123 map->add_feature (feature->tag, feature->value, (feature->start == 0 && feat ure->end == (unsigned int) -1));
131 } 124 }
132 } 125 }
133 126
134 127
128 /*
129 * shaper face data
130 */
131
132 hb_ot_shaper_face_data_t *
133 _hb_ot_shaper_face_data_create (hb_face_t *face)
134 {
135 return _hb_ot_layout_create (face);
136 }
137
138 void
139 _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
140 {
141 _hb_ot_layout_destroy (data);
142 }
143
144
145 /*
146 * shaper font data
147 */
148
149 struct hb_ot_shaper_font_data_t {};
150
151 hb_ot_shaper_font_data_t *
152 _hb_ot_shaper_font_data_create (hb_font_t *font)
153 {
154 return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
155 }
156
157 void
158 _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
159 {
160 }
161
162
163 /*
164 * shaper shape_plan data
165 */
166
167 hb_ot_shaper_shape_plan_data_t *
168 _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
169 const hb_feature_t *user_features,
170 unsigned int num_user_features)
171 {
172 hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_sha pe_plan_t));
173 if (unlikely (!plan))
174 return NULL;
175
176 hb_ot_shape_planner_t planner (shape_plan);
177
178 planner.shaper = hb_ot_shape_complex_categorize (&shape_plan->props);
179
180 hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num _user_features);
181
182 planner.compile (*plan);
183
184 if (plan->shaper->data_create) {
185 plan->data = plan->shaper->data_create (plan);
186 if (unlikely (!plan->data))
187 return NULL;
188 }
189
190 return plan;
191 }
192
193 void
194 _hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
195 {
196 if (plan->shaper->data_destroy)
197 plan->shaper->data_destroy (const_cast<void *> (plan->data));
198
199 plan->finish ();
200
201 free (plan);
202 }
203
204
205 /*
206 * shaper
207 */
208
135 struct hb_ot_shape_context_t 209 struct hb_ot_shape_context_t
136 { 210 {
137 /* Input to hb_ot_shape_execute() */
138 hb_ot_shape_plan_t *plan; 211 hb_ot_shape_plan_t *plan;
139 hb_font_t *font; 212 hb_font_t *font;
140 hb_face_t *face; 213 hb_face_t *face;
141 hb_buffer_t *buffer; 214 hb_buffer_t *buffer;
142 const hb_feature_t *user_features; 215 const hb_feature_t *user_features;
143 unsigned int num_user_features; 216 unsigned int num_user_features;
144 217
145 /* Transient stuff */ 218 /* Transient stuff */
146 hb_direction_t target_direction; 219 hb_direction_t target_direction;
147 hb_bool_t applied_position_complex;
148 }; 220 };
149 221
150 static void
151 hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
152 {
153 hb_mask_t global_mask = c->plan->map.get_global_mask ();
154 c->buffer->reset_masks (global_mask);
155
156 hb_ot_shape_complex_setup_masks (c->plan->shaper, &c->plan->map, c->buffer, c- >font);
157
158 for (unsigned int i = 0; i < c->num_user_features; i++)
159 {
160 const hb_feature_t *feature = &c->user_features[i];
161 if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
162 unsigned int shift;
163 hb_mask_t mask = c->plan->map.get_mask (feature->tag, &shift);
164 c->buffer->set_masks (feature->value << shift, mask, feature->start, featu re->end);
165 }
166 }
167 }
168 222
169 223
170 /* Main shaper */ 224 /* Main shaper */
171 225
226
172 /* Prepare */ 227 /* Prepare */
173 228
174 static void 229 static void
175 hb_set_unicode_props (hb_buffer_t *buffer) 230 hb_set_unicode_props (hb_buffer_t *buffer)
176 { 231 {
177 unsigned int count = buffer->len; 232 unsigned int count = buffer->len;
178 for (unsigned int i = 0; i < count; i++) 233 for (unsigned int i = 0; i < count; i++)
179 _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode); 234 _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
180 } 235 }
181 236
182 static void 237 static void
238 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
239 {
240 /* TODO One day, when we keep _before_ text for the buffer, take
241 * that into consideration. For now, insert dotted-circle if the
242 * very first character is a non-spacing mark. */
243 if (_hb_glyph_info_get_general_category (&buffer->info[0]) !=
244 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
245 return;
246
247 hb_codepoint_t dottedcircle_glyph;
248 if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
249 return;
250
251 hb_glyph_info_t dottedcircle;
252 dottedcircle.codepoint = 0x25CC;
253 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
254
255 buffer->clear_output ();
256
257 buffer->idx = 0;
258 hb_glyph_info_t info = dottedcircle;
259 info.cluster = buffer->cur().cluster;
260 info.mask = buffer->cur().mask;
261 buffer->output_info (info);
262 while (buffer->idx < buffer->len)
263 buffer->next_glyph ();
264
265 buffer->swap_buffers ();
266 }
267
268 static void
183 hb_form_clusters (hb_buffer_t *buffer) 269 hb_form_clusters (hb_buffer_t *buffer)
184 { 270 {
185 unsigned int count = buffer->len; 271 unsigned int count = buffer->len;
186 for (unsigned int i = 1; i < count; i++) 272 for (unsigned int i = 1; i < count; i++)
187 if (FLAG (_hb_glyph_info_get_general_category (&buffer->info[i])) & 273 if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
188 » (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | 274 buffer->merge_clusters (i - 1, i + 1);
189 » FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
190 » FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
191 buffer->info[i].cluster = buffer->info[i - 1].cluster; /* XXX do the min() here */
192 } 275 }
193 276
194 static void 277 static void
195 hb_ensure_native_direction (hb_buffer_t *buffer) 278 hb_ensure_native_direction (hb_buffer_t *buffer)
196 { 279 {
197 hb_direction_t direction = buffer->props.direction; 280 hb_direction_t direction = buffer->props.direction;
198 281
199 /* TODO vertical: 282 /* TODO vertical:
200 * The only BTT vertical script is Ogham, but it's not clear to me whether Ope nType 283 * The only BTT vertical script is Ogham, but it's not clear to me whether Ope nType
201 * Ogham fonts are supposed to be implemented BTT or not. Need to research th at 284 * Ogham fonts are supposed to be implemented BTT or not. Need to research th at
202 * first. */ 285 * first. */
203 if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_hori zontal_direction (buffer->props.script)) || 286 if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_hori zontal_direction (buffer->props.script)) ||
204 (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) 287 (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB))
205 { 288 {
206 hb_buffer_reverse_clusters (buffer); 289 hb_buffer_reverse_clusters (buffer);
207 buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction); 290 buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
208 } 291 }
209 } 292 }
210 293
211 294
212 /* Substitute */ 295 /* Substitute */
213 296
214 static void 297 static inline void
215 hb_mirror_chars (hb_ot_shape_context_t *c) 298 hb_ot_mirror_chars (hb_ot_shape_context_t *c)
216 { 299 {
217 hb_unicode_funcs_t *unicode = c->buffer->unicode;
218
219 if (HB_DIRECTION_IS_FORWARD (c->target_direction)) 300 if (HB_DIRECTION_IS_FORWARD (c->target_direction))
220 return; 301 return;
221 302
303 hb_unicode_funcs_t *unicode = c->buffer->unicode;
222 hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); 304 hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m'));
223 305
224 unsigned int count = c->buffer->len; 306 unsigned int count = c->buffer->len;
225 for (unsigned int i = 0; i < count; i++) { 307 for (unsigned int i = 0; i < count; i++) {
226 hb_codepoint_t codepoint = hb_unicode_mirroring (unicode, c->buffer->info[i] .codepoint); 308 hb_codepoint_t codepoint = unicode->mirroring (c->buffer->info[i].codepoint) ;
227 if (likely (codepoint == c->buffer->info[i].codepoint)) 309 if (likely (codepoint == c->buffer->info[i].codepoint))
228 c->buffer->info[i].mask |= rtlm_mask; /* XXX this should be moved to befor e setting user-feature masks */ 310 c->buffer->info[i].mask |= rtlm_mask;
229 else 311 else
230 c->buffer->info[i].codepoint = codepoint; 312 c->buffer->info[i].codepoint = codepoint;
231 } 313 }
232 } 314 }
233 315
234 static void 316 static inline void
235 hb_map_glyphs (hb_font_t *font, 317 hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
236 » hb_buffer_t *buffer)
237 { 318 {
238 hb_codepoint_t glyph; 319 hb_ot_map_t *map = &c->plan->map;
239 320
240 if (unlikely (!buffer->len)) 321 hb_mask_t global_mask = map->get_global_mask ();
241 return; 322 c->buffer->reset_masks (global_mask);
242 323
243 buffer->clear_output (); 324 if (c->plan->shaper->setup_masks)
325 c->plan->shaper->setup_masks (c->plan, c->buffer, c->font);
244 326
245 unsigned int count = buffer->len - 1; 327 for (unsigned int i = 0; i < c->num_user_features; i++)
246 for (buffer->idx = 0; buffer->idx < count;) { 328 {
247 if (unlikely (_hb_unicode_is_variation_selector (buffer->cur(+1).codepoint)) ) { 329 const hb_feature_t *feature = &c->user_features[i];
248 hb_font_get_glyph (font, buffer->cur().codepoint, buffer->cur(+1).codepoin t, &glyph); 330 if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
249 buffer->replace_glyphs (2, 1, &glyph); 331 unsigned int shift;
250 } else { 332 hb_mask_t mask = map->get_mask (feature->tag, &shift);
251 hb_font_get_glyph (font, buffer->cur().codepoint, 0, &glyph); 333 c->buffer->set_masks (feature->value << shift, mask, feature->start, featu re->end);
252 buffer->replace_glyph (glyph);
253 } 334 }
254 } 335 }
255 if (likely (buffer->idx < buffer->len)) {
256 hb_font_get_glyph (font, buffer->cur().codepoint, 0, &glyph);
257 buffer->replace_glyph (glyph);
258 }
259 buffer->swap_buffers ();
260 } 336 }
261 337
262 static void 338 static inline void
263 hb_substitute_default (hb_ot_shape_context_t *c) 339 hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
264 { 340 {
265 hb_ot_layout_substitute_start (c->buffer); 341 /* Normalization process sets up glyph_index(), we just copy it. */
266 342 unsigned int count = buffer->len;
267 hb_mirror_chars (c); 343 for (unsigned int i = 0; i < count; i++)
268 344 buffer->info[i].codepoint = buffer->info[i].glyph_index();
269 hb_map_glyphs (c->font, c->buffer);
270 } 345 }
271 346
272 static void 347 static inline void
348 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
349 {
350 unsigned int count = c->buffer->len;
351 for (unsigned int i = 0; i < count; i++)
352 c->buffer->info[i].glyph_props() = _hb_glyph_info_get_general_category (&c-> buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ?
353 » » » » HB_OT_LAYOUT_GLYPH_CLASS_MARK :
354 » » » » HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
355 }
356
357 static inline void
358 hb_ot_substitute_default (hb_ot_shape_context_t *c)
359 {
360 if (c->plan->shaper->preprocess_text)
361 c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
362
363 hb_ot_mirror_chars (c);
364
365 HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index);
366
367 _hb_ot_shape_normalize (c->font, c->buffer,
368 » » » c->plan->shaper->normalization_preference ?
369 » » » c->plan->shaper->normalization_preference (c->plan) :
370 » » » HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT);
371
372 hb_ot_shape_setup_masks (c);
373
374 /* This is unfortunate to go here, but necessary... */
375 if (!hb_ot_layout_has_positioning (c->face))
376 _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, c->buff er);
377
378 hb_ot_map_glyphs_fast (c->buffer);
379
380 HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index);
381 }
382
383 static inline void
273 hb_ot_substitute_complex (hb_ot_shape_context_t *c) 384 hb_ot_substitute_complex (hb_ot_shape_context_t *c)
274 { 385 {
275 if (hb_ot_layout_has_substitution (c->face)) { 386 hb_ot_layout_substitute_start (c->font, c->buffer);
276 c->plan->map.substitute (c->face, c->buffer);
277 }
278 387
279 hb_ot_layout_substitute_finish (c->buffer); 388 if (!hb_ot_layout_has_glyph_classes (c->face))
389 hb_synthesize_glyph_classes (c);
390
391 c->plan->substitute (c->font, c->buffer);
392
393 hb_ot_layout_substitute_finish (c->font, c->buffer);
280 394
281 return; 395 return;
282 } 396 }
283 397
398 static inline void
399 hb_ot_substitute (hb_ot_shape_context_t *c)
400 {
401 hb_ot_substitute_default (c);
402 hb_ot_substitute_complex (c);
403 }
284 404
285 /* Position */ 405 /* Position */
286 406
287 static void 407 static inline void
288 hb_position_default (hb_ot_shape_context_t *c) 408 hb_ot_position_default (hb_ot_shape_context_t *c)
289 { 409 {
290 hb_ot_layout_position_start (c->buffer); 410 hb_ot_layout_position_start (c->font, c->buffer);
291 411
292 unsigned int count = c->buffer->len; 412 unsigned int count = c->buffer->len;
293 for (unsigned int i = 0; i < count; i++) { 413 for (unsigned int i = 0; i < count; i++) {
294 hb_font_get_glyph_advance_for_direction (c->font, c->buffer->info[i].codepoi nt, 414 c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint,
295 » » » » » c->buffer->props.direction, 415 » » » » » c->buffer->props.direction,
296 » » » » » &c->buffer->pos[i].x_advance, 416 » » » » » &c->buffer->pos[i].x_advance,
297 » » » » » &c->buffer->pos[i].y_advance); 417 » » » » » &c->buffer->pos[i].y_advance);
298 hb_font_subtract_glyph_origin_for_direction (c->font, c->buffer->info[i].cod epoint, 418 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint,
299 » » » » » » c->buffer->props.direction, 419 » » » » » » c->buffer->props.direction,
300 » » » » » » &c->buffer->pos[i].x_offset, 420 » » » » » » &c->buffer->pos[i].x_offset,
301 » » » » » » &c->buffer->pos[i].y_offset); 421 » » » » » » &c->buffer->pos[i].y_offset);
302 } 422 }
303 } 423 }
304 424
305 static void 425 static inline bool
306 hb_ot_position_complex (hb_ot_shape_context_t *c) 426 hb_ot_position_complex (hb_ot_shape_context_t *c)
307 { 427 {
428 bool ret = false;
308 429
309 if (hb_ot_layout_has_positioning (c->face)) 430 if (hb_ot_layout_has_positioning (c->face))
310 { 431 {
311 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ 432 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
312 433
313 unsigned int count = c->buffer->len; 434 unsigned int count = c->buffer->len;
314 for (unsigned int i = 0; i < count; i++) { 435 for (unsigned int i = 0; i < count; i++) {
315 hb_font_add_glyph_origin_for_direction (c->font, c->buffer->info[i].codepo int, 436 c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint,
316 » » » » » HB_DIRECTION_LTR, 437 » » » » » HB_DIRECTION_LTR,
317 » » » » » &c->buffer->pos[i].x_offset, 438 » » » » » &c->buffer->pos[i].x_offset,
318 » » » » » &c->buffer->pos[i].y_offset); 439 » » » » » &c->buffer->pos[i].y_offset);
319 } 440 }
320 441
321 c->plan->map.position (c->font, c->buffer); 442 c->plan->position (c->font, c->buffer);
322 443
323 for (unsigned int i = 0; i < count; i++) { 444 for (unsigned int i = 0; i < count; i++) {
324 hb_font_subtract_glyph_origin_for_direction (c->font, c->buffer->info[i].c odepoint, 445 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint ,
325 » » » » » » HB_DIRECTION_LTR, 446 » » » » » » HB_DIRECTION_LTR,
326 » » » » » » &c->buffer->pos[i].x_offset, 447 » » » » » » &c->buffer->pos[i].x_offset,
327 » » » » » » &c->buffer->pos[i].y_offset); 448 » » » » » » &c->buffer->pos[i].y_offset) ;
328 } 449 }
329 450
330 c->applied_position_complex = true; 451 ret = true;
331 } 452 }
332 453
333 hb_ot_layout_position_finish (c->buffer); 454 hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_ attached_marks);
334 455
335 return; 456 return ret;
336 } 457 }
337 458
338 static void 459 static inline void
339 hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED) 460 hb_ot_position_complex_fallback (hb_ot_shape_context_t *c)
340 { 461 {
341 /* TODO Mark pos */ 462 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
342 } 463 }
343 464
344 static void 465 static inline void
345 hb_truetype_kern (hb_ot_shape_context_t *c) 466 hb_ot_truetype_kern (hb_ot_shape_context_t *c)
346 { 467 {
347 /* TODO Check for kern=0 */ 468 /* TODO Check for kern=0 */
348 unsigned int count = c->buffer->len; 469 unsigned int count = c->buffer->len;
349 for (unsigned int i = 1; i < count; i++) { 470 for (unsigned int i = 1; i < count; i++) {
350 hb_position_t x_kern, y_kern, kern1, kern2; 471 hb_position_t x_kern, y_kern, kern1, kern2;
351 hb_font_get_glyph_kerning_for_direction (c->font, 472 c->font->get_glyph_kerning_for_direction (c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint,
352 » » » » » c->buffer->info[i - 1].codepoint, c ->buffer->info[i].codepoint, 473 » » » » » c->buffer->props.direction,
353 » » » » » c->buffer->props.direction, 474 » » » » » &x_kern, &y_kern);
354 » » » » » &x_kern, &y_kern);
355 475
356 kern1 = x_kern >> 1; 476 kern1 = x_kern >> 1;
357 kern2 = x_kern - kern1; 477 kern2 = x_kern - kern1;
358 c->buffer->pos[i - 1].x_advance += kern1; 478 c->buffer->pos[i - 1].x_advance += kern1;
359 c->buffer->pos[i].x_advance += kern2; 479 c->buffer->pos[i].x_advance += kern2;
360 c->buffer->pos[i].x_offset += kern2; 480 c->buffer->pos[i].x_offset += kern2;
361 481
362 kern1 = y_kern >> 1; 482 kern1 = y_kern >> 1;
363 kern2 = y_kern - kern1; 483 kern2 = y_kern - kern1;
364 c->buffer->pos[i - 1].y_advance += kern1; 484 c->buffer->pos[i - 1].y_advance += kern1;
365 c->buffer->pos[i].y_advance += kern2; 485 c->buffer->pos[i].y_advance += kern2;
366 c->buffer->pos[i].y_offset += kern2; 486 c->buffer->pos[i].y_offset += kern2;
367 } 487 }
368 } 488 }
369 489
370 static void 490 static inline void
371 hb_position_complex_fallback_visual (hb_ot_shape_context_t *c) 491 hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
372 { 492 {
373 hb_truetype_kern (c); 493 hb_ot_truetype_kern (c);
374 } 494 }
375 495
496 static inline void
497 hb_ot_position (hb_ot_shape_context_t *c)
498 {
499 hb_ot_position_default (c);
500
501 hb_bool_t fallback = !hb_ot_position_complex (c);
502
503 if (fallback)
504 hb_ot_position_complex_fallback (c);
505
506 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
507 hb_buffer_reverse (c->buffer);
508
509 if (fallback)
510 hb_position_complex_fallback_visual (c);
511 }
512
513
514 /* Post-process */
515
376 static void 516 static void
377 hb_hide_zerowidth (hb_ot_shape_context_t *c) 517 hb_ot_hide_zerowidth (hb_ot_shape_context_t *c)
378 { 518 {
379 /* TODO Save the space character in the font? */ 519 hb_codepoint_t space = 0;
380 hb_codepoint_t space;
381 if (!hb_font_get_glyph (c->font, ' ', 0, &space))
382 return; /* No point! */
383 520
384 unsigned int count = c->buffer->len; 521 unsigned int count = c->buffer->len;
385 for (unsigned int i = 0; i < count; i++) 522 for (unsigned int i = 0; i < count; i++)
386 if (unlikely (_hb_glyph_info_is_zero_width (&c->buffer->info[i]))) { 523 if (unlikely (!is_a_ligature (c->buffer->info[i]) &&
524 » » _hb_glyph_info_is_zero_width (&c->buffer->info[i])))
525 {
526 if (!space) {
527 /* We assume that the space glyph is not gid0. */
528 if (unlikely (!c->font->get_glyph (' ', 0, &space)) || !space)
529 » return; /* No point! */
530 }
387 c->buffer->info[i].codepoint = space; 531 c->buffer->info[i].codepoint = space;
388 c->buffer->pos[i].x_advance = 0; 532 c->buffer->pos[i].x_advance = 0;
389 c->buffer->pos[i].y_advance = 0; 533 c->buffer->pos[i].y_advance = 0;
390 } 534 }
391 } 535 }
392 536
393 537
394 /* Do it! */ 538 /* Pull it all together! */
395 539
396 static void 540 static void
397 hb_ot_shape_execute_internal (hb_ot_shape_context_t *c) 541 hb_ot_shape_internal (hb_ot_shape_context_t *c)
398 { 542 {
399 c->buffer->deallocate_var_all (); 543 c->buffer->deallocate_var_all ();
400 544
401 /* Save the original direction, we use it later. */ 545 /* Save the original direction, we use it later. */
402 c->target_direction = c->buffer->props.direction; 546 c->target_direction = c->buffer->props.direction;
403 547
404 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props0); 548 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props0);
405 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props1); 549 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props1);
406 550
551 c->buffer->clear_output ();
552
407 hb_set_unicode_props (c->buffer); 553 hb_set_unicode_props (c->buffer);
408 554 hb_insert_dotted_circle (c->buffer, c->font);
409 hb_form_clusters (c->buffer); 555 hb_form_clusters (c->buffer);
410 556
411 hb_ensure_native_direction (c->buffer); 557 hb_ensure_native_direction (c->buffer);
412 558
413 _hb_ot_shape_normalize (c->font, c->buffer, hb_ot_shape_complex_normalization_ preference (c->plan->shaper)); 559 hb_ot_substitute (c);
560 hb_ot_position (c);
414 561
415 hb_ot_shape_setup_masks (c); 562 hb_ot_hide_zerowidth (c);
416
417 /* SUBSTITUTE */
418 {
419 hb_substitute_default (c);
420
421 hb_ot_substitute_complex (c);
422 }
423
424 /* POSITION */
425 {
426 hb_position_default (c);
427
428 hb_ot_position_complex (c);
429
430 hb_bool_t position_fallback = !c->applied_position_complex;
431 if (position_fallback)
432 hb_position_complex_fallback (c);
433
434 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
435 hb_buffer_reverse (c->buffer);
436
437 if (position_fallback)
438 hb_position_complex_fallback_visual (c);
439 }
440
441 hb_hide_zerowidth (c);
442 563
443 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1); 564 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1);
444 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0); 565 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0);
445 566
446 c->buffer->props.direction = c->target_direction; 567 c->buffer->props.direction = c->target_direction;
447 568
448 c->buffer->deallocate_var_all (); 569 c->buffer->deallocate_var_all ();
449 } 570 }
450 571
451 static void
452 hb_ot_shape_plan_internal (hb_ot_shape_plan_t *plan,
453 hb_face_t *face,
454 const hb_segment_properties_t *props,
455 const hb_feature_t *user_features,
456 unsigned int num_user_features)
457 {
458 hb_ot_shape_planner_t planner;
459
460 assert (HB_DIRECTION_IS_VALID (props->direction));
461
462 planner.shaper = hb_ot_shape_complex_categorize (props);
463
464 hb_ot_shape_collect_features (&planner, props, user_features, num_user_feature s);
465
466 planner.compile (face, props, *plan);
467 }
468
469 static void
470 hb_ot_shape_execute (hb_ot_shape_plan_t *plan,
471 hb_font_t *font,
472 hb_buffer_t *buffer,
473 const hb_feature_t *user_features,
474 unsigned int num_user_features)
475 {
476 hb_ot_shape_context_t c = {plan, font, font->face, buffer, user_features, num_ user_features};
477 hb_ot_shape_execute_internal (&c);
478 }
479 572
480 hb_bool_t 573 hb_bool_t
481 _hb_ot_shape (hb_font_t *font, 574 _hb_ot_shape (hb_shape_plan_t *shape_plan,
575 » hb_font_t *font,
482 hb_buffer_t *buffer, 576 hb_buffer_t *buffer,
483 const hb_feature_t *features, 577 const hb_feature_t *features,
484 unsigned int num_features) 578 unsigned int num_features)
485 { 579 {
486 hb_ot_shape_plan_t plan; 580 hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
487 581 hb_ot_shape_internal (&c);
488 buffer->guess_properties ();
489
490 hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_fe atures);
491 hb_ot_shape_execute (&plan, font, buffer, features, num_features);
492 582
493 return true; 583 return true;
494 } 584 }
495 585
496 586
587
588 static inline void
589 hb_ot_map_glyphs_dumb (hb_font_t *font,
590 hb_buffer_t *buffer)
591 {
592 unsigned int count = buffer->len;
593 for (unsigned int i = 0; i < count; i++)
594 font->get_glyph (buffer->cur().codepoint, 0, &buffer->cur().codepoint);
595 }
596
497 void 597 void
498 hb_ot_shape_glyphs_closure (hb_font_t *font, 598 hb_ot_shape_glyphs_closure (hb_font_t *font,
499 hb_buffer_t *buffer, 599 hb_buffer_t *buffer,
500 const hb_feature_t *features, 600 const hb_feature_t *features,
501 unsigned int num_features, 601 unsigned int num_features,
502 hb_set_t *glyphs) 602 hb_set_t *glyphs)
503 { 603 {
504 hb_ot_shape_plan_t plan; 604 hb_ot_shape_plan_t plan;
505 605
506 buffer->guess_properties (); 606 buffer->guess_properties ();
507 607
508 hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_fe atures); 608 /* TODO cache / ensure correct backend, etc. */
609 hb_shape_plan_t *shape_plan = hb_shape_plan_create (font->face, &buffer->props , features, num_features, NULL);
509 610
510 /* TODO: normalization? have shapers do closure()? */ 611 /* TODO: normalization? have shapers do closure()? */
511 /* TODO: Deal with mirrored chars? */ 612 /* TODO: Deal with mirrored chars? */
512 hb_map_glyphs (font, buffer); 613 hb_ot_map_glyphs_dumb (font, buffer);
513 614
514 /* Seed it. It's user's responsibility to have cleard glyphs 615 /* Seed it. It's user's responsibility to have cleard glyphs
515 * if that's what they desire. */ 616 * if that's what they desire. */
516 unsigned int count = buffer->len; 617 unsigned int count = buffer->len;
517 for (unsigned int i = 0; i < count; i++) 618 for (unsigned int i = 0; i < count; i++)
518 hb_set_add (glyphs, buffer->info[i].codepoint); 619 glyphs->add (buffer->info[i].codepoint);
519 620
520 /* And find transitive closure. */ 621 /* And find transitive closure. */
521 hb_set_t copy; 622 hb_set_t copy;
522 copy.init (); 623 copy.init ();
523 624
524 do { 625 do {
525 copy.set (glyphs); 626 copy.set (glyphs);
526 plan.map.substitute_closure (font->face, glyphs); 627 HB_SHAPER_DATA_GET (shape_plan)->substitute_closure (font->face, glyphs);
527 } while (!copy.equal (glyphs)); 628 } while (!copy.equal (glyphs));
629
630 hb_shape_plan_destroy (shape_plan);
528 } 631 }
OLDNEW
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-ot-name-table.hh ('k') | third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698