OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2009,2010 Red Hat, Inc. | 2 * Copyright © 2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2011,2012 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 |
(...skipping 11 matching lines...) Expand all Loading... |
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 | 29 #define HB_SHAPER ot |
30 #define hb_ot_shaper_face_data_t hb_ot_layout_t | 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 | 31 #define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t |
32 #include "hb-shaper-impl-private.hh" | 32 |
| 33 #include "hb-ot-layout-private.hh" |
33 | 34 |
34 #include "hb-ot-shape-private.hh" | 35 #include "hb-ot-shape-private.hh" |
35 #include "hb-ot-shape-complex-private.hh" | 36 #include "hb-ot-shape-complex-private.hh" |
36 #include "hb-ot-shape-fallback-private.hh" | 37 #include "hb-ot-shape-fallback-private.hh" |
37 #include "hb-ot-shape-normalize-private.hh" | 38 #include "hb-ot-shape-normalize-private.hh" |
38 | 39 |
39 #include "hb-ot-layout-private.hh" | |
40 #include "hb-set-private.hh" | 40 #include "hb-set-private.hh" |
| 41 #include "hb-shaper-impl-private.hh" |
| 42 |
| 43 #include "hb-unicode-private.hh" |
41 | 44 |
42 | 45 |
43 static hb_tag_t common_features[] = { | 46 static hb_tag_t common_features[] = { |
44 HB_TAG('c','c','m','p'), | 47 HB_TAG('c','c','m','p'), |
45 HB_TAG('l','i','g','a'), | 48 HB_TAG('l','i','g','a'), |
46 HB_TAG('l','o','c','l'), | 49 HB_TAG('l','o','c','l'), |
47 HB_TAG('m','a','r','k'), | 50 HB_TAG('m','a','r','k'), |
48 HB_TAG('m','k','m','k'), | 51 HB_TAG('m','k','m','k'), |
49 HB_TAG('r','l','i','g'), | 52 HB_TAG('r','l','i','g'), |
50 }; | 53 }; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 | 222 |
220 /* Main shaper */ | 223 /* Main shaper */ |
221 | 224 |
222 | 225 |
223 /* Prepare */ | 226 /* Prepare */ |
224 | 227 |
225 static void | 228 static void |
226 hb_set_unicode_props (hb_buffer_t *buffer) | 229 hb_set_unicode_props (hb_buffer_t *buffer) |
227 { | 230 { |
228 unsigned int count = buffer->len; | 231 unsigned int count = buffer->len; |
| 232 hb_glyph_info_t *info = buffer->info; |
229 for (unsigned int i = 0; i < count; i++) | 233 for (unsigned int i = 0; i < count; i++) |
230 _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode); | 234 _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode); |
231 } | 235 } |
232 | 236 |
233 static void | 237 static void |
234 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) | 238 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) |
235 { | 239 { |
236 if (!(buffer->flags & HB_BUFFER_FLAG_BOT) || | 240 if (!(buffer->flags & HB_BUFFER_FLAG_BOT) || |
237 _hb_glyph_info_get_general_category (&buffer->info[0]) != | 241 _hb_glyph_info_get_general_category (&buffer->info[0]) != |
238 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | 242 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
239 return; | 243 return; |
240 | 244 |
241 if (!font->has_glyph (0x25CC)) | 245 if (!font->has_glyph (0x25CCu)) |
242 return; | 246 return; |
243 | 247 |
244 hb_glyph_info_t dottedcircle; | 248 hb_glyph_info_t dottedcircle; |
245 dottedcircle.codepoint = 0x25CC; | 249 dottedcircle.codepoint = 0x25CCu; |
246 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); | 250 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); |
247 | 251 |
248 buffer->clear_output (); | 252 buffer->clear_output (); |
249 | 253 |
250 buffer->idx = 0; | 254 buffer->idx = 0; |
251 hb_glyph_info_t info = dottedcircle; | 255 hb_glyph_info_t info = dottedcircle; |
252 info.cluster = buffer->cur().cluster; | 256 info.cluster = buffer->cur().cluster; |
253 info.mask = buffer->cur().mask; | 257 info.mask = buffer->cur().mask; |
254 buffer->output_info (info); | 258 buffer->output_info (info); |
255 while (buffer->idx < buffer->len) | 259 while (buffer->idx < buffer->len) |
256 buffer->next_glyph (); | 260 buffer->next_glyph (); |
257 | 261 |
258 buffer->swap_buffers (); | 262 buffer->swap_buffers (); |
259 } | 263 } |
260 | 264 |
261 static void | 265 static void |
262 hb_form_clusters (hb_buffer_t *buffer) | 266 hb_form_clusters (hb_buffer_t *buffer) |
263 { | 267 { |
264 unsigned int count = buffer->len; | 268 unsigned int count = buffer->len; |
| 269 hb_glyph_info_t *info = buffer->info; |
265 for (unsigned int i = 1; i < count; i++) | 270 for (unsigned int i = 1; i < count; i++) |
266 if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category
(&buffer->info[i]))) | 271 if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category
(&info[i]))) |
267 buffer->merge_clusters (i - 1, i + 1); | 272 buffer->merge_clusters (i - 1, i + 1); |
268 } | 273 } |
269 | 274 |
270 static void | 275 static void |
271 hb_ensure_native_direction (hb_buffer_t *buffer) | 276 hb_ensure_native_direction (hb_buffer_t *buffer) |
272 { | 277 { |
273 hb_direction_t direction = buffer->props.direction; | 278 hb_direction_t direction = buffer->props.direction; |
274 | 279 |
275 /* TODO vertical: | 280 /* TODO vertical: |
276 * The only BTT vertical script is Ogham, but it's not clear to me whether Ope
nType | 281 * The only BTT vertical script is Ogham, but it's not clear to me whether Ope
nType |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 if (!c->plan->has_frac) | 319 if (!c->plan->has_frac) |
315 return; | 320 return; |
316 | 321 |
317 hb_buffer_t *buffer = c->buffer; | 322 hb_buffer_t *buffer = c->buffer; |
318 | 323 |
319 /* TODO look in pre/post context text also. */ | 324 /* TODO look in pre/post context text also. */ |
320 unsigned int count = buffer->len; | 325 unsigned int count = buffer->len; |
321 hb_glyph_info_t *info = buffer->info; | 326 hb_glyph_info_t *info = buffer->info; |
322 for (unsigned int i = 0; i < count; i++) | 327 for (unsigned int i = 0; i < count; i++) |
323 { | 328 { |
324 if (info[i].codepoint == 0x2044) /* FRACTION SLASH */ | 329 if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */ |
325 { | 330 { |
326 unsigned int start = i, end = i + 1; | 331 unsigned int start = i, end = i + 1; |
327 while (start && | 332 while (start && |
328 _hb_glyph_info_get_general_category (&info[start - 1]) == | 333 _hb_glyph_info_get_general_category (&info[start - 1]) == |
329 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | 334 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
330 start--; | 335 start--; |
331 while (end < count && | 336 while (end < count && |
332 _hb_glyph_info_get_general_category (&info[end]) == | 337 _hb_glyph_info_get_general_category (&info[end]) == |
333 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | 338 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
334 end++; | 339 end++; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 buffer->set_masks (feature->value << shift, mask, feature->start, feature-
>end); | 379 buffer->set_masks (feature->value << shift, mask, feature->start, feature-
>end); |
375 } | 380 } |
376 } | 381 } |
377 } | 382 } |
378 | 383 |
379 static inline void | 384 static inline void |
380 hb_ot_map_glyphs_fast (hb_buffer_t *buffer) | 385 hb_ot_map_glyphs_fast (hb_buffer_t *buffer) |
381 { | 386 { |
382 /* Normalization process sets up glyph_index(), we just copy it. */ | 387 /* Normalization process sets up glyph_index(), we just copy it. */ |
383 unsigned int count = buffer->len; | 388 unsigned int count = buffer->len; |
| 389 hb_glyph_info_t *info = buffer->info; |
384 for (unsigned int i = 0; i < count; i++) | 390 for (unsigned int i = 0; i < count; i++) |
385 buffer->info[i].codepoint = buffer->info[i].glyph_index(); | 391 info[i].codepoint = info[i].glyph_index(); |
386 } | 392 } |
387 | 393 |
388 static inline void | 394 static inline void |
389 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) | 395 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) |
390 { | 396 { |
391 unsigned int count = c->buffer->len; | 397 unsigned int count = c->buffer->len; |
392 hb_glyph_info_t *info = c->buffer->info; | 398 hb_glyph_info_t *info = c->buffer->info; |
393 for (unsigned int i = 0; i < count; i++) | 399 for (unsigned int i = 0; i < count; i++) |
394 _hb_glyph_info_set_glyph_props (&info[i], | 400 { |
395 » » » » _hb_glyph_info_get_general_category (&info[i
]) | 401 hb_ot_layout_glyph_class_mask_t klass; |
396 » » » » == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_M
ARK ? | 402 |
397 » » » » HB_OT_LAYOUT_GLYPH_PROPS_MARK : | 403 /* Never mark default-ignorables as marks. |
398 » » » » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); | 404 * They won't get in the way of lookups anyway, |
| 405 * but having them as mark will cause them to be skipped |
| 406 * over if the lookup-flag says so, but at least for the |
| 407 * Mongolian variation selectors, looks like Uniscribe |
| 408 * marks them as non-mark. Some Mongolian fonts without |
| 409 * GDEF rely on this. Another notable character that |
| 410 * this applies to is COMBINING GRAPHEME JOINER. */ |
| 411 klass = (_hb_glyph_info_get_general_category (&info[i]) != |
| 412 » HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || |
| 413 » _hb_glyph_info_is_default_ignorable (&info[i])) ? |
| 414 » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : |
| 415 » HB_OT_LAYOUT_GLYPH_PROPS_MARK; |
| 416 _hb_glyph_info_set_glyph_props (&info[i], klass); |
| 417 } |
399 } | 418 } |
400 | 419 |
401 static inline void | 420 static inline void |
402 hb_ot_substitute_default (hb_ot_shape_context_t *c) | 421 hb_ot_substitute_default (hb_ot_shape_context_t *c) |
403 { | 422 { |
404 hb_buffer_t *buffer = c->buffer; | 423 hb_buffer_t *buffer = c->buffer; |
405 | 424 |
406 if (c->plan->shaper->preprocess_text) | 425 if (c->plan->shaper->preprocess_text) |
407 c->plan->shaper->preprocess_text (c->plan, buffer, c->font); | 426 c->plan->shaper->preprocess_text (c->plan, buffer, c->font); |
408 | 427 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 static inline void | 464 static inline void |
446 hb_ot_substitute (hb_ot_shape_context_t *c) | 465 hb_ot_substitute (hb_ot_shape_context_t *c) |
447 { | 466 { |
448 hb_ot_substitute_default (c); | 467 hb_ot_substitute_default (c); |
449 hb_ot_substitute_complex (c); | 468 hb_ot_substitute_complex (c); |
450 } | 469 } |
451 | 470 |
452 /* Position */ | 471 /* Position */ |
453 | 472 |
454 static inline void | 473 static inline void |
455 zero_mark_widths_by_unicode (hb_buffer_t *buffer) | 474 adjust_mark_offsets (hb_glyph_position_t *pos) |
| 475 { |
| 476 pos->x_offset -= pos->x_advance; |
| 477 pos->y_offset -= pos->y_advance; |
| 478 } |
| 479 |
| 480 static inline void |
| 481 zero_mark_width (hb_glyph_position_t *pos) |
| 482 { |
| 483 pos->x_advance = 0; |
| 484 pos->y_advance = 0; |
| 485 } |
| 486 |
| 487 static inline void |
| 488 zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets) |
456 { | 489 { |
457 unsigned int count = buffer->len; | 490 unsigned int count = buffer->len; |
| 491 hb_glyph_info_t *info = buffer->info; |
458 for (unsigned int i = 0; i < count; i++) | 492 for (unsigned int i = 0; i < count; i++) |
459 if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GEN
ERAL_CATEGORY_NON_SPACING_MARK) | 493 if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CAT
EGORY_NON_SPACING_MARK) |
460 { | 494 { |
461 buffer->pos[i].x_advance = 0; | 495 if (adjust_offsets) |
462 buffer->pos[i].y_advance = 0; | 496 adjust_mark_offsets (&buffer->pos[i]); |
| 497 zero_mark_width (&buffer->pos[i]); |
463 } | 498 } |
464 } | 499 } |
465 | 500 |
466 static inline void | 501 static inline void |
467 zero_mark_widths_by_gdef (hb_buffer_t *buffer) | 502 zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets) |
468 { | 503 { |
469 unsigned int count = buffer->len; | 504 unsigned int count = buffer->len; |
| 505 hb_glyph_info_t *info = buffer->info; |
470 for (unsigned int i = 0; i < count; i++) | 506 for (unsigned int i = 0; i < count; i++) |
471 if (_hb_glyph_info_is_mark (&buffer->info[i])) | 507 if (_hb_glyph_info_is_mark (&info[i])) |
472 { | 508 { |
473 buffer->pos[i].x_advance = 0; | 509 if (adjust_offsets) |
474 buffer->pos[i].y_advance = 0; | 510 adjust_mark_offsets (&buffer->pos[i]); |
| 511 zero_mark_width (&buffer->pos[i]); |
475 } | 512 } |
476 } | 513 } |
477 | 514 |
478 static inline void | 515 static inline void |
479 hb_ot_position_default (hb_ot_shape_context_t *c) | 516 hb_ot_position_default (hb_ot_shape_context_t *c) |
480 { | 517 { |
481 hb_direction_t direction = c->buffer->props.direction; | 518 hb_direction_t direction = c->buffer->props.direction; |
482 unsigned int count = c->buffer->len; | 519 unsigned int count = c->buffer->len; |
483 hb_glyph_info_t *info = c->buffer->info; | 520 hb_glyph_info_t *info = c->buffer->info; |
484 hb_glyph_position_t *pos = c->buffer->pos; | 521 hb_glyph_position_t *pos = c->buffer->pos; |
485 for (unsigned int i = 0; i < count; i++) | 522 for (unsigned int i = 0; i < count; i++) |
486 { | 523 { |
487 c->font->get_glyph_advance_for_direction (info[i].codepoint, | 524 c->font->get_glyph_advance_for_direction (info[i].codepoint, |
488 direction, | 525 direction, |
489 &pos[i].x_advance, | 526 &pos[i].x_advance, |
490 &pos[i].y_advance); | 527 &pos[i].y_advance); |
491 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, | 528 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
492 direction, | 529 direction, |
493 &pos[i].x_offset, | 530 &pos[i].x_offset, |
494 &pos[i].y_offset); | 531 &pos[i].y_offset); |
495 | 532 |
496 } | 533 } |
497 } | 534 } |
498 | 535 |
499 static inline bool | 536 static inline bool |
500 hb_ot_position_complex (hb_ot_shape_context_t *c) | 537 hb_ot_position_complex (hb_ot_shape_context_t *c) |
501 { | 538 { |
502 bool ret = false; | 539 bool ret = false; |
503 unsigned int count = c->buffer->len; | 540 unsigned int count = c->buffer->len; |
| 541 bool has_positioning = hb_ot_layout_has_positioning (c->face); |
| 542 /* If the font has no GPOS, AND, no fallback positioning will |
| 543 * happen, AND, direction is forward, then when zeroing mark |
| 544 * widths, we shift the mark with it, such that the mark |
| 545 * is positioned hanging over the previous glyph. When |
| 546 * direction is backward we don't shift and it will end up |
| 547 * hanging over the next glyph after the final reordering. |
| 548 * If fallback positinoing happens or GPOS is present, we don't |
| 549 * care. |
| 550 */ |
| 551 bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallb
ack_position || |
| 552 HB_DIRECTION_IS_BACKWARD (c->buffer->prop
s.direction)); |
504 | 553 |
505 switch (c->plan->shaper->zero_width_marks) | 554 switch (c->plan->shaper->zero_width_marks) |
506 { | 555 { |
507 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 556 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
508 zero_mark_widths_by_gdef (c->buffer); | 557 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
509 break; | 558 break; |
510 | 559 |
511 /* Not currently used for any shaper: | 560 /* Not currently used for any shaper: |
512 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 561 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
513 zero_mark_widths_by_unicode (c->buffer); | 562 zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); |
514 break; | 563 break; |
515 */ | 564 */ |
516 | 565 |
517 default: | 566 default: |
518 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 567 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
519 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 568 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
520 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 569 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
521 break; | 570 break; |
522 } | 571 } |
523 | 572 |
524 if (hb_ot_layout_has_positioning (c->face)) | 573 if (has_positioning) |
525 { | 574 { |
526 hb_glyph_info_t *info = c->buffer->info; | 575 hb_glyph_info_t *info = c->buffer->info; |
527 hb_glyph_position_t *pos = c->buffer->pos; | 576 hb_glyph_position_t *pos = c->buffer->pos; |
528 | 577 |
529 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ | 578 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ |
530 | 579 |
531 for (unsigned int i = 0; i < count; i++) { | 580 for (unsigned int i = 0; i < count; i++) { |
532 c->font->add_glyph_origin_for_direction (info[i].codepoint, | 581 c->font->add_glyph_origin_for_direction (info[i].codepoint, |
533 HB_DIRECTION_LTR, | 582 HB_DIRECTION_LTR, |
534 &pos[i].x_offset, | 583 &pos[i].x_offset, |
535 &pos[i].y_offset); | 584 &pos[i].y_offset); |
536 } | 585 } |
537 | 586 |
538 c->plan->position (c->font, c->buffer); | 587 c->plan->position (c->font, c->buffer); |
539 | 588 |
540 for (unsigned int i = 0; i < count; i++) { | 589 for (unsigned int i = 0; i < count; i++) { |
541 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, | 590 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
542 HB_DIRECTION_LTR, | 591 HB_DIRECTION_LTR, |
543 &pos[i].x_offset, | 592 &pos[i].x_offset, |
544 &pos[i].y_offset); | 593 &pos[i].y_offset); |
545 } | 594 } |
546 | 595 |
547 ret = true; | 596 ret = true; |
548 } | 597 } |
549 | 598 |
550 switch (c->plan->shaper->zero_width_marks) | 599 switch (c->plan->shaper->zero_width_marks) |
551 { | 600 { |
552 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 601 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
553 zero_mark_widths_by_unicode (c->buffer); | 602 zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); |
554 break; | 603 break; |
555 | 604 |
556 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 605 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
557 zero_mark_widths_by_gdef (c->buffer); | 606 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
558 break; | 607 break; |
559 | 608 |
560 default: | 609 default: |
561 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 610 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
562 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 611 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
563 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 612 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
564 break; | 613 break; |
565 } | 614 } |
566 | 615 |
567 return ret; | 616 return ret; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 { | 773 { |
725 hb_ot_shape_plan_t plan; | 774 hb_ot_shape_plan_t plan; |
726 | 775 |
727 const char *shapers[] = {"ot", NULL}; | 776 const char *shapers[] = {"ot", NULL}; |
728 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer
->props, | 777 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer
->props, |
729 features, num_featu
res, shapers); | 778 features, num_featu
res, shapers); |
730 | 779 |
731 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_
DIRECTION_RTL; | 780 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_
DIRECTION_RTL; |
732 | 781 |
733 unsigned int count = buffer->len; | 782 unsigned int count = buffer->len; |
| 783 hb_glyph_info_t *info = buffer->info; |
734 for (unsigned int i = 0; i < count; i++) | 784 for (unsigned int i = 0; i < count; i++) |
735 add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs); | 785 add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs); |
736 | 786 |
737 hb_set_t lookups; | 787 hb_set_t lookups; |
738 lookups.init (); | 788 lookups.init (); |
739 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); | 789 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); |
740 | 790 |
741 /* And find transitive closure. */ | 791 /* And find transitive closure. */ |
742 hb_set_t copy; | 792 hb_set_t copy; |
743 copy.init (); | 793 copy.init (); |
744 do { | 794 do { |
745 copy.set (glyphs); | 795 copy.set (glyphs); |
746 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) | 796 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) |
747 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); | 797 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
748 } while (!copy.is_equal (glyphs)); | 798 } while (!copy.is_equal (glyphs)); |
749 | 799 |
750 hb_shape_plan_destroy (shape_plan); | 800 hb_shape_plan_destroy (shape_plan); |
751 } | 801 } |
OLD | NEW |