| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 static void | 76 static void |
| 77 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, | 77 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, |
| 78 const hb_segment_properties_t *props, | 78 const hb_segment_properties_t *props, |
| 79 const hb_feature_t *user_features, | 79 const hb_feature_t *user_features, |
| 80 unsigned int num_user_features) | 80 unsigned int num_user_features) |
| 81 { | 81 { |
| 82 hb_ot_map_builder_t *map = &planner->map; | 82 hb_ot_map_builder_t *map = &planner->map; |
| 83 | 83 |
| 84 switch (props->direction) { | 84 switch (props->direction) { |
| 85 case HB_DIRECTION_LTR: | 85 case HB_DIRECTION_LTR: |
| 86 map->add_bool_feature (HB_TAG ('l','t','r','a')); | 86 map->add_global_bool_feature (HB_TAG ('l','t','r','a')); |
| 87 map->add_bool_feature (HB_TAG ('l','t','r','m')); | 87 map->add_global_bool_feature (HB_TAG ('l','t','r','m')); |
| 88 break; | 88 break; |
| 89 case HB_DIRECTION_RTL: | 89 case HB_DIRECTION_RTL: |
| 90 map->add_bool_feature (HB_TAG ('r','t','l','a')); | 90 map->add_global_bool_feature (HB_TAG ('r','t','l','a')); |
| 91 map->add_bool_feature (HB_TAG ('r','t','l','m'), false); | 91 map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE); |
| 92 break; | 92 break; |
| 93 case HB_DIRECTION_TTB: | 93 case HB_DIRECTION_TTB: |
| 94 case HB_DIRECTION_BTT: | 94 case HB_DIRECTION_BTT: |
| 95 case HB_DIRECTION_INVALID: | 95 case HB_DIRECTION_INVALID: |
| 96 default: | 96 default: |
| 97 break; | 97 break; |
| 98 } | 98 } |
| 99 | 99 |
| 100 #define ADD_FEATURES(array) \ | |
| 101 HB_STMT_START { \ | |
| 102 for (unsigned int i = 0; i < ARRAY_LENGTH (array); i++) \ | |
| 103 map->add_bool_feature (array[i]); \ | |
| 104 } HB_STMT_END | |
| 105 | |
| 106 if (planner->shaper->collect_features) | 100 if (planner->shaper->collect_features) |
| 107 planner->shaper->collect_features (planner); | 101 planner->shaper->collect_features (planner); |
| 108 | 102 |
| 109 ADD_FEATURES (common_features); | 103 for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) |
| 104 map->add_global_bool_feature (common_features[i]); |
| 110 | 105 |
| 111 if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) | 106 if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) |
| 112 ADD_FEATURES (horizontal_features); | 107 for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++) |
| 108 map->add_feature (horizontal_features[i], 1, F_GLOBAL | |
| 109 » » » (horizontal_features[i] == HB_TAG('k','e','r','n') ? |
| 110 » » » F_HAS_FALLBACK : F_NONE)); |
| 113 else | 111 else |
| 114 ADD_FEATURES (vertical_features); | 112 for (unsigned int i = 0; i < ARRAY_LENGTH (vertical_features); i++) |
| 113 map->add_feature (vertical_features[i], 1, F_GLOBAL | |
| 114 » » » (vertical_features[i] == HB_TAG('v','k','r','n') ? |
| 115 » » » F_HAS_FALLBACK : F_NONE)); |
| 115 | 116 |
| 116 if (planner->shaper->override_features) | 117 if (planner->shaper->override_features) |
| 117 planner->shaper->override_features (planner); | 118 planner->shaper->override_features (planner); |
| 118 | 119 |
| 119 #undef ADD_FEATURES | |
| 120 | |
| 121 for (unsigned int i = 0; i < num_user_features; i++) { | 120 for (unsigned int i = 0; i < num_user_features; i++) { |
| 122 const hb_feature_t *feature = &user_features[i]; | 121 const hb_feature_t *feature = &user_features[i]; |
| 123 map->add_feature (feature->tag, feature->value, (feature->start == 0 && feat
ure->end == (unsigned int) -1)); | 122 map->add_feature (feature->tag, feature->value, |
| 123 » » (feature->start == 0 && feature->end == (unsigned int) -1)
? |
| 124 » » F_GLOBAL : F_NONE); |
| 124 } | 125 } |
| 125 } | 126 } |
| 126 | 127 |
| 127 | 128 |
| 128 /* | 129 /* |
| 129 * shaper face data | 130 * shaper face data |
| 130 */ | 131 */ |
| 131 | 132 |
| 132 hb_ot_shaper_face_data_t * | 133 hb_ot_shaper_face_data_t * |
| 133 _hb_ot_shaper_face_data_create (hb_face_t *face) | 134 _hb_ot_shaper_face_data_create (hb_face_t *face) |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 } | 399 } |
| 399 | 400 |
| 400 /* Position */ | 401 /* Position */ |
| 401 | 402 |
| 402 static inline void | 403 static inline void |
| 403 hb_ot_position_default (hb_ot_shape_context_t *c) | 404 hb_ot_position_default (hb_ot_shape_context_t *c) |
| 404 { | 405 { |
| 405 hb_ot_layout_position_start (c->font, c->buffer); | 406 hb_ot_layout_position_start (c->font, c->buffer); |
| 406 | 407 |
| 407 unsigned int count = c->buffer->len; | 408 unsigned int count = c->buffer->len; |
| 408 for (unsigned int i = 0; i < count; i++) { | 409 for (unsigned int i = 0; i < count; i++) |
| 410 { |
| 409 c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint, | 411 c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint, |
| 410 c->buffer->props.direction, | 412 c->buffer->props.direction, |
| 411 &c->buffer->pos[i].x_advance, | 413 &c->buffer->pos[i].x_advance, |
| 412 &c->buffer->pos[i].y_advance); | 414 &c->buffer->pos[i].y_advance); |
| 413 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint, | 415 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint, |
| 414 c->buffer->props.direction, | 416 c->buffer->props.direction, |
| 415 &c->buffer->pos[i].x_offset, | 417 &c->buffer->pos[i].x_offset, |
| 416 &c->buffer->pos[i].y_offset); | 418 &c->buffer->pos[i].y_offset); |
| 419 |
| 420 } |
| 421 |
| 422 /* Zero'ing mark widths by GDEF (as used in Myanmar spec) happens |
| 423 * *before* GPOS. */ |
| 424 switch (c->plan->shaper->zero_width_marks) |
| 425 { |
| 426 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF: |
| 427 for (unsigned int i = 0; i < count; i++) |
| 428 if ((c->buffer->info[i].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) |
| 429 { |
| 430 c->buffer->pos[i].x_advance = 0; |
| 431 c->buffer->pos[i].y_advance = 0; |
| 432 } |
| 433 break; |
| 434 |
| 435 default: |
| 436 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 437 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE: |
| 438 break; |
| 417 } | 439 } |
| 418 } | 440 } |
| 419 | 441 |
| 420 static inline bool | 442 static inline bool |
| 421 hb_ot_position_complex (hb_ot_shape_context_t *c) | 443 hb_ot_position_complex (hb_ot_shape_context_t *c) |
| 422 { | 444 { |
| 423 bool ret = false; | 445 bool ret = false; |
| 446 unsigned int count = c->buffer->len; |
| 424 | 447 |
| 425 if (hb_ot_layout_has_positioning (c->face)) | 448 if (hb_ot_layout_has_positioning (c->face)) |
| 426 { | 449 { |
| 427 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ | 450 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ |
| 428 | 451 |
| 429 unsigned int count = c->buffer->len; | |
| 430 for (unsigned int i = 0; i < count; i++) { | 452 for (unsigned int i = 0; i < count; i++) { |
| 431 c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint, | 453 c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint, |
| 432 HB_DIRECTION_LTR, | 454 HB_DIRECTION_LTR, |
| 433 &c->buffer->pos[i].x_offset, | 455 &c->buffer->pos[i].x_offset, |
| 434 &c->buffer->pos[i].y_offset); | 456 &c->buffer->pos[i].y_offset); |
| 435 } | 457 } |
| 436 | 458 |
| 437 c->plan->position (c->font, c->buffer); | 459 c->plan->position (c->font, c->buffer); |
| 438 | 460 |
| 439 for (unsigned int i = 0; i < count; i++) { | 461 for (unsigned int i = 0; i < count; i++) { |
| 440 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint
, | 462 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint
, |
| 441 HB_DIRECTION_LTR, | 463 HB_DIRECTION_LTR, |
| 442 &c->buffer->pos[i].x_offset, | 464 &c->buffer->pos[i].x_offset, |
| 443 &c->buffer->pos[i].y_offset)
; | 465 &c->buffer->pos[i].y_offset)
; |
| 444 } | 466 } |
| 445 | 467 |
| 446 ret = true; | 468 ret = true; |
| 447 } | 469 } |
| 448 | 470 |
| 449 hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_
attached_marks); | 471 /* Zero'ing mark widths by Unicode happens |
| 472 * *after* GPOS. */ |
| 473 switch (c->plan->shaper->zero_width_marks) |
| 474 { |
| 475 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE: |
| 476 for (unsigned int i = 0; i < count; i++) |
| 477 » if (_hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNIC
ODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
| 478 » { |
| 479 » c->buffer->pos[i].x_advance = 0; |
| 480 » c->buffer->pos[i].y_advance = 0; |
| 481 » } |
| 482 break; |
| 483 |
| 484 default: |
| 485 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 486 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF: |
| 487 break; |
| 488 } |
| 489 |
| 490 hb_ot_layout_position_finish (c->font, c->buffer); |
| 450 | 491 |
| 451 return ret; | 492 return ret; |
| 452 } | 493 } |
| 453 | 494 |
| 454 static inline void | 495 static inline void |
| 455 hb_ot_truetype_kern (hb_ot_shape_context_t *c) | |
| 456 { | |
| 457 /* TODO Check for kern=0 */ | |
| 458 unsigned int count = c->buffer->len; | |
| 459 for (unsigned int i = 1; i < count; i++) { | |
| 460 hb_position_t x_kern, y_kern, kern1, kern2; | |
| 461 c->font->get_glyph_kerning_for_direction (c->buffer->info[i - 1].codepoint,
c->buffer->info[i].codepoint, | |
| 462 c->buffer->props.direction, | |
| 463 &x_kern, &y_kern); | |
| 464 | |
| 465 kern1 = x_kern >> 1; | |
| 466 kern2 = x_kern - kern1; | |
| 467 c->buffer->pos[i - 1].x_advance += kern1; | |
| 468 c->buffer->pos[i].x_advance += kern2; | |
| 469 c->buffer->pos[i].x_offset += kern2; | |
| 470 | |
| 471 kern1 = y_kern >> 1; | |
| 472 kern2 = y_kern - kern1; | |
| 473 c->buffer->pos[i - 1].y_advance += kern1; | |
| 474 c->buffer->pos[i].y_advance += kern2; | |
| 475 c->buffer->pos[i].y_offset += kern2; | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 static inline void | |
| 480 hb_ot_position (hb_ot_shape_context_t *c) | 496 hb_ot_position (hb_ot_shape_context_t *c) |
| 481 { | 497 { |
| 482 hb_ot_position_default (c); | 498 hb_ot_position_default (c); |
| 483 | 499 |
| 484 hb_bool_t fallback = !hb_ot_position_complex (c); | 500 hb_bool_t fallback = !hb_ot_position_complex (c); |
| 485 | 501 |
| 486 if (fallback && c->plan->shaper->fallback_position) | 502 if (fallback && c->plan->shaper->fallback_position) |
| 487 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); | 503 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); |
| 488 | 504 |
| 489 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) | 505 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) |
| 490 hb_buffer_reverse (c->buffer); | 506 hb_buffer_reverse (c->buffer); |
| 491 | 507 |
| 492 /* Visual fallback goes here. */ | 508 /* Visual fallback goes here. */ |
| 493 | 509 |
| 494 if (fallback) | 510 if (fallback) |
| 495 hb_ot_truetype_kern (c); | 511 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); |
| 496 } | 512 } |
| 497 | 513 |
| 498 | 514 |
| 499 /* Post-process */ | 515 /* Post-process */ |
| 500 | 516 |
| 501 static void | 517 static void |
| 502 hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) | 518 hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) |
| 503 { | 519 { |
| 504 if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) | 520 if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) |
| 505 return; | 521 return; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 | 620 |
| 605 void | 621 void |
| 606 hb_ot_shape_glyphs_closure (hb_font_t *font, | 622 hb_ot_shape_glyphs_closure (hb_font_t *font, |
| 607 hb_buffer_t *buffer, | 623 hb_buffer_t *buffer, |
| 608 const hb_feature_t *features, | 624 const hb_feature_t *features, |
| 609 unsigned int num_features, | 625 unsigned int num_features, |
| 610 hb_set_t *glyphs) | 626 hb_set_t *glyphs) |
| 611 { | 627 { |
| 612 hb_ot_shape_plan_t plan; | 628 hb_ot_shape_plan_t plan; |
| 613 | 629 |
| 614 buffer->guess_segment_properties (); | |
| 615 | |
| 616 const char *shapers[] = {"ot", NULL}; | 630 const char *shapers[] = {"ot", NULL}; |
| 617 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer
->props, | 631 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer
->props, |
| 618 features, num_featu
res, shapers); | 632 features, num_featu
res, shapers); |
| 619 | 633 |
| 620 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_
DIRECTION_RTL; | 634 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_
DIRECTION_RTL; |
| 621 | 635 |
| 622 unsigned int count = buffer->len; | 636 unsigned int count = buffer->len; |
| 623 for (unsigned int i = 0; i < count; i++) | 637 for (unsigned int i = 0; i < count; i++) |
| 624 add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs); | 638 add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs); |
| 625 | 639 |
| 626 hb_set_t lookups; | 640 hb_set_t lookups; |
| 627 lookups.init (); | 641 lookups.init (); |
| 628 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); | 642 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); |
| 629 | 643 |
| 630 /* And find transitive closure. */ | 644 /* And find transitive closure. */ |
| 631 hb_set_t copy; | 645 hb_set_t copy; |
| 632 copy.init (); | 646 copy.init (); |
| 633 do { | 647 do { |
| 634 copy.set (glyphs); | 648 copy.set (glyphs); |
| 635 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) | 649 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) |
| 636 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); | 650 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
| 637 } while (!copy.is_equal (glyphs)); | 651 } while (!copy.is_equal (glyphs)); |
| 638 | 652 |
| 639 hb_shape_plan_destroy (shape_plan); | 653 hb_shape_plan_destroy (shape_plan); |
| 640 } | 654 } |
| OLD | NEW |