| 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 19 matching lines...) Expand all Loading... |
| 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 #include "hb-shaper-impl-private.hh" |
| 33 | 33 |
| 34 #include "hb-ot-shape-private.hh" | 34 #include "hb-ot-shape-private.hh" |
| 35 #include "hb-ot-shape-complex-private.hh" | 35 #include "hb-ot-shape-complex-private.hh" |
| 36 #include "hb-ot-shape-fallback-private.hh" | 36 #include "hb-ot-shape-fallback-private.hh" |
| 37 #include "hb-ot-shape-normalize-private.hh" | 37 #include "hb-ot-shape-normalize-private.hh" |
| 38 | 38 |
| 39 #include "hb-ot-layout-private.hh" | 39 #include "hb-ot-layout-private.hh" |
| 40 #include "hb-unicode-private.hh" |
| 40 #include "hb-set-private.hh" | 41 #include "hb-set-private.hh" |
| 41 | 42 |
| 42 | 43 |
| 43 static hb_tag_t common_features[] = { | 44 static hb_tag_t common_features[] = { |
| 44 HB_TAG('c','c','m','p'), | 45 HB_TAG('c','c','m','p'), |
| 45 HB_TAG('l','i','g','a'), | 46 HB_TAG('l','i','g','a'), |
| 46 HB_TAG('l','o','c','l'), | 47 HB_TAG('l','o','c','l'), |
| 47 HB_TAG('m','a','r','k'), | 48 HB_TAG('m','a','r','k'), |
| 48 HB_TAG('m','k','m','k'), | 49 HB_TAG('m','k','m','k'), |
| 49 HB_TAG('r','l','i','g'), | 50 HB_TAG('r','l','i','g'), |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 } | 232 } |
| 232 | 233 |
| 233 static void | 234 static void |
| 234 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) | 235 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) |
| 235 { | 236 { |
| 236 if (!(buffer->flags & HB_BUFFER_FLAG_BOT) || | 237 if (!(buffer->flags & HB_BUFFER_FLAG_BOT) || |
| 237 _hb_glyph_info_get_general_category (&buffer->info[0]) != | 238 _hb_glyph_info_get_general_category (&buffer->info[0]) != |
| 238 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | 239 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
| 239 return; | 240 return; |
| 240 | 241 |
| 241 if (!font->has_glyph (0x25CC)) | 242 if (!font->has_glyph (0x25CCu)) |
| 242 return; | 243 return; |
| 243 | 244 |
| 244 hb_glyph_info_t dottedcircle; | 245 hb_glyph_info_t dottedcircle; |
| 245 dottedcircle.codepoint = 0x25CC; | 246 dottedcircle.codepoint = 0x25CCu; |
| 246 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); | 247 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode); |
| 247 | 248 |
| 248 buffer->clear_output (); | 249 buffer->clear_output (); |
| 249 | 250 |
| 250 buffer->idx = 0; | 251 buffer->idx = 0; |
| 251 hb_glyph_info_t info = dottedcircle; | 252 hb_glyph_info_t info = dottedcircle; |
| 252 info.cluster = buffer->cur().cluster; | 253 info.cluster = buffer->cur().cluster; |
| 253 info.mask = buffer->cur().mask; | 254 info.mask = buffer->cur().mask; |
| 254 buffer->output_info (info); | 255 buffer->output_info (info); |
| 255 while (buffer->idx < buffer->len) | 256 while (buffer->idx < buffer->len) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 if (!c->plan->has_frac) | 315 if (!c->plan->has_frac) |
| 315 return; | 316 return; |
| 316 | 317 |
| 317 hb_buffer_t *buffer = c->buffer; | 318 hb_buffer_t *buffer = c->buffer; |
| 318 | 319 |
| 319 /* TODO look in pre/post context text also. */ | 320 /* TODO look in pre/post context text also. */ |
| 320 unsigned int count = buffer->len; | 321 unsigned int count = buffer->len; |
| 321 hb_glyph_info_t *info = buffer->info; | 322 hb_glyph_info_t *info = buffer->info; |
| 322 for (unsigned int i = 0; i < count; i++) | 323 for (unsigned int i = 0; i < count; i++) |
| 323 { | 324 { |
| 324 if (info[i].codepoint == 0x2044) /* FRACTION SLASH */ | 325 if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */ |
| 325 { | 326 { |
| 326 unsigned int start = i, end = i + 1; | 327 unsigned int start = i, end = i + 1; |
| 327 while (start && | 328 while (start && |
| 328 _hb_glyph_info_get_general_category (&info[start - 1]) == | 329 _hb_glyph_info_get_general_category (&info[start - 1]) == |
| 329 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | 330 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
| 330 start--; | 331 start--; |
| 331 while (end < count && | 332 while (end < count && |
| 332 _hb_glyph_info_get_general_category (&info[end]) == | 333 _hb_glyph_info_get_general_category (&info[end]) == |
| 333 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | 334 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
| 334 end++; | 335 end++; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 for (unsigned int i = 0; i < count; i++) | 385 for (unsigned int i = 0; i < count; i++) |
| 385 buffer->info[i].codepoint = buffer->info[i].glyph_index(); | 386 buffer->info[i].codepoint = buffer->info[i].glyph_index(); |
| 386 } | 387 } |
| 387 | 388 |
| 388 static inline void | 389 static inline void |
| 389 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) | 390 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) |
| 390 { | 391 { |
| 391 unsigned int count = c->buffer->len; | 392 unsigned int count = c->buffer->len; |
| 392 hb_glyph_info_t *info = c->buffer->info; | 393 hb_glyph_info_t *info = c->buffer->info; |
| 393 for (unsigned int i = 0; i < count; i++) | 394 for (unsigned int i = 0; i < count; i++) |
| 394 _hb_glyph_info_set_glyph_props (&info[i], | 395 { |
| 395 » » » » _hb_glyph_info_get_general_category (&info[i
]) | 396 hb_ot_layout_glyph_class_mask_t klass; |
| 396 » » » » == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_M
ARK ? | 397 |
| 397 » » » » HB_OT_LAYOUT_GLYPH_PROPS_MARK : | 398 /* Never mark default-ignorables as marks. |
| 398 » » » » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); | 399 * They won't get in the way of lookups anyway, |
| 400 * but having them as mark will cause them to be skipped |
| 401 * over if the lookup-flag says so, but at least for the |
| 402 * Mongolian variation selectors, looks like Uniscribe |
| 403 * marks them as non-mark. Some Mongolian fonts without |
| 404 * GDEF rely on this. Another notable character that |
| 405 * this applies to is COMBINING GRAPHEME JOINER. */ |
| 406 klass = (_hb_glyph_info_get_general_category (&info[i]) != |
| 407 » HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || |
| 408 » _hb_glyph_info_is_default_ignorable (&info[i])) ? |
| 409 » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : |
| 410 » HB_OT_LAYOUT_GLYPH_PROPS_MARK; |
| 411 _hb_glyph_info_set_glyph_props (&info[i], klass); |
| 412 } |
| 399 } | 413 } |
| 400 | 414 |
| 401 static inline void | 415 static inline void |
| 402 hb_ot_substitute_default (hb_ot_shape_context_t *c) | 416 hb_ot_substitute_default (hb_ot_shape_context_t *c) |
| 403 { | 417 { |
| 404 hb_buffer_t *buffer = c->buffer; | 418 hb_buffer_t *buffer = c->buffer; |
| 405 | 419 |
| 406 if (c->plan->shaper->preprocess_text) | 420 if (c->plan->shaper->preprocess_text) |
| 407 c->plan->shaper->preprocess_text (c->plan, buffer, c->font); | 421 c->plan->shaper->preprocess_text (c->plan, buffer, c->font); |
| 408 | 422 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 static inline void | 459 static inline void |
| 446 hb_ot_substitute (hb_ot_shape_context_t *c) | 460 hb_ot_substitute (hb_ot_shape_context_t *c) |
| 447 { | 461 { |
| 448 hb_ot_substitute_default (c); | 462 hb_ot_substitute_default (c); |
| 449 hb_ot_substitute_complex (c); | 463 hb_ot_substitute_complex (c); |
| 450 } | 464 } |
| 451 | 465 |
| 452 /* Position */ | 466 /* Position */ |
| 453 | 467 |
| 454 static inline void | 468 static inline void |
| 455 zero_mark_widths_by_unicode (hb_buffer_t *buffer) | 469 adjust_mark_offsets (hb_glyph_position_t *pos) |
| 470 { |
| 471 pos->x_offset -= pos->x_advance; |
| 472 pos->y_offset -= pos->y_advance; |
| 473 } |
| 474 |
| 475 static inline void |
| 476 zero_mark_width (hb_glyph_position_t *pos) |
| 477 { |
| 478 pos->x_advance = 0; |
| 479 pos->y_advance = 0; |
| 480 } |
| 481 |
| 482 static inline void |
| 483 zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets) |
| 456 { | 484 { |
| 457 unsigned int count = buffer->len; | 485 unsigned int count = buffer->len; |
| 458 for (unsigned int i = 0; i < count; i++) | 486 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) | 487 if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GEN
ERAL_CATEGORY_NON_SPACING_MARK) |
| 460 { | 488 { |
| 461 buffer->pos[i].x_advance = 0; | 489 if (adjust_offsets) |
| 462 buffer->pos[i].y_advance = 0; | 490 adjust_mark_offsets (&buffer->pos[i]); |
| 491 zero_mark_width (&buffer->pos[i]); |
| 463 } | 492 } |
| 464 } | 493 } |
| 465 | 494 |
| 466 static inline void | 495 static inline void |
| 467 zero_mark_widths_by_gdef (hb_buffer_t *buffer) | 496 zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets) |
| 468 { | 497 { |
| 469 unsigned int count = buffer->len; | 498 unsigned int count = buffer->len; |
| 470 for (unsigned int i = 0; i < count; i++) | 499 for (unsigned int i = 0; i < count; i++) |
| 471 if (_hb_glyph_info_is_mark (&buffer->info[i])) | 500 if (_hb_glyph_info_is_mark (&buffer->info[i])) |
| 472 { | 501 { |
| 473 buffer->pos[i].x_advance = 0; | 502 if (adjust_offsets) |
| 474 buffer->pos[i].y_advance = 0; | 503 adjust_mark_offsets (&buffer->pos[i]); |
| 504 zero_mark_width (&buffer->pos[i]); |
| 475 } | 505 } |
| 476 } | 506 } |
| 477 | 507 |
| 478 static inline void | 508 static inline void |
| 479 hb_ot_position_default (hb_ot_shape_context_t *c) | 509 hb_ot_position_default (hb_ot_shape_context_t *c) |
| 480 { | 510 { |
| 481 hb_direction_t direction = c->buffer->props.direction; | 511 hb_direction_t direction = c->buffer->props.direction; |
| 482 unsigned int count = c->buffer->len; | 512 unsigned int count = c->buffer->len; |
| 483 hb_glyph_info_t *info = c->buffer->info; | 513 hb_glyph_info_t *info = c->buffer->info; |
| 484 hb_glyph_position_t *pos = c->buffer->pos; | 514 hb_glyph_position_t *pos = c->buffer->pos; |
| 485 for (unsigned int i = 0; i < count; i++) | 515 for (unsigned int i = 0; i < count; i++) |
| 486 { | 516 { |
| 487 c->font->get_glyph_advance_for_direction (info[i].codepoint, | 517 c->font->get_glyph_advance_for_direction (info[i].codepoint, |
| 488 direction, | 518 direction, |
| 489 &pos[i].x_advance, | 519 &pos[i].x_advance, |
| 490 &pos[i].y_advance); | 520 &pos[i].y_advance); |
| 491 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, | 521 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
| 492 direction, | 522 direction, |
| 493 &pos[i].x_offset, | 523 &pos[i].x_offset, |
| 494 &pos[i].y_offset); | 524 &pos[i].y_offset); |
| 495 | 525 |
| 496 } | 526 } |
| 497 } | 527 } |
| 498 | 528 |
| 499 static inline bool | 529 static inline bool |
| 500 hb_ot_position_complex (hb_ot_shape_context_t *c) | 530 hb_ot_position_complex (hb_ot_shape_context_t *c) |
| 501 { | 531 { |
| 502 bool ret = false; | 532 bool ret = false; |
| 503 unsigned int count = c->buffer->len; | 533 unsigned int count = c->buffer->len; |
| 534 bool has_positioning = hb_ot_layout_has_positioning (c->face); |
| 535 /* If the font has no GPOS, AND, no fallback positioning will |
| 536 * happen, AND, direction is forward, then when zeroing mark |
| 537 * widths, we shift the mark with it, such that the mark |
| 538 * is positioned hanging over the previous glyph. When |
| 539 * direction is backward we don't shift and it will end up |
| 540 * hanging over the next glyph after the final reordering. |
| 541 * If fallback positinoing happens or GPOS is present, we don't |
| 542 * care. |
| 543 */ |
| 544 bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallb
ack_position || |
| 545 HB_DIRECTION_IS_BACKWARD (c->buffer->prop
s.direction)); |
| 504 | 546 |
| 505 switch (c->plan->shaper->zero_width_marks) | 547 switch (c->plan->shaper->zero_width_marks) |
| 506 { | 548 { |
| 507 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 549 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
| 508 zero_mark_widths_by_gdef (c->buffer); | 550 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
| 509 break; | 551 break; |
| 510 | 552 |
| 511 /* Not currently used for any shaper: | 553 /* Not currently used for any shaper: |
| 512 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 554 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
| 513 zero_mark_widths_by_unicode (c->buffer); | 555 zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); |
| 514 break; | 556 break; |
| 515 */ | 557 */ |
| 516 | 558 |
| 517 default: | 559 default: |
| 518 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 560 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 519 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 561 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
| 520 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 562 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
| 521 break; | 563 break; |
| 522 } | 564 } |
| 523 | 565 |
| 524 if (hb_ot_layout_has_positioning (c->face)) | 566 if (has_positioning) |
| 525 { | 567 { |
| 526 hb_glyph_info_t *info = c->buffer->info; | 568 hb_glyph_info_t *info = c->buffer->info; |
| 527 hb_glyph_position_t *pos = c->buffer->pos; | 569 hb_glyph_position_t *pos = c->buffer->pos; |
| 528 | 570 |
| 529 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ | 571 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ |
| 530 | 572 |
| 531 for (unsigned int i = 0; i < count; i++) { | 573 for (unsigned int i = 0; i < count; i++) { |
| 532 c->font->add_glyph_origin_for_direction (info[i].codepoint, | 574 c->font->add_glyph_origin_for_direction (info[i].codepoint, |
| 533 HB_DIRECTION_LTR, | 575 HB_DIRECTION_LTR, |
| 534 &pos[i].x_offset, | 576 &pos[i].x_offset, |
| 535 &pos[i].y_offset); | 577 &pos[i].y_offset); |
| 536 } | 578 } |
| 537 | 579 |
| 538 c->plan->position (c->font, c->buffer); | 580 c->plan->position (c->font, c->buffer); |
| 539 | 581 |
| 540 for (unsigned int i = 0; i < count; i++) { | 582 for (unsigned int i = 0; i < count; i++) { |
| 541 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, | 583 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
| 542 HB_DIRECTION_LTR, | 584 HB_DIRECTION_LTR, |
| 543 &pos[i].x_offset, | 585 &pos[i].x_offset, |
| 544 &pos[i].y_offset); | 586 &pos[i].y_offset); |
| 545 } | 587 } |
| 546 | 588 |
| 547 ret = true; | 589 ret = true; |
| 548 } | 590 } |
| 549 | 591 |
| 550 switch (c->plan->shaper->zero_width_marks) | 592 switch (c->plan->shaper->zero_width_marks) |
| 551 { | 593 { |
| 552 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 594 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
| 553 zero_mark_widths_by_unicode (c->buffer); | 595 zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing); |
| 554 break; | 596 break; |
| 555 | 597 |
| 556 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 598 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
| 557 zero_mark_widths_by_gdef (c->buffer); | 599 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
| 558 break; | 600 break; |
| 559 | 601 |
| 560 default: | 602 default: |
| 561 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 603 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 562 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 604 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
| 563 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 605 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
| 564 break; | 606 break; |
| 565 } | 607 } |
| 566 | 608 |
| 567 return ret; | 609 return ret; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 hb_set_t copy; | 784 hb_set_t copy; |
| 743 copy.init (); | 785 copy.init (); |
| 744 do { | 786 do { |
| 745 copy.set (glyphs); | 787 copy.set (glyphs); |
| 746 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) | 788 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); | 789 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
| 748 } while (!copy.is_equal (glyphs)); | 790 } while (!copy.is_equal (glyphs)); |
| 749 | 791 |
| 750 hb_shape_plan_destroy (shape_plan); | 792 hb_shape_plan_destroy (shape_plan); |
| 751 } | 793 } |
| OLD | NEW |