1 /* 2 * Copyright 1998-2004 David Turner and Werner Lemberg 3 * Copyright 2004,2007,2009,2010 Red Hat, Inc. 4 * Copyright 2011,2012 Google, Inc. 5 * 6 * This is part of HarfBuzz, a text shaping library. 7 * 8 * Permission is hereby granted, without written agreement and without 9 * license or royalty fees, to use, copy, modify, and distribute this 10 * software and its documentation for any purpose, provided that the 11 * above copyright notice and the following two paragraphs appear in 12 * all copies of this software. 13 * 14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 18 * DAMAGE. 19 * 20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 * 26 * Red Hat Author(s): Owen Taylor, Behdad Esfahbod 27 * Google Author(s): Behdad Esfahbod 28 */ 29 30 #include "hb-buffer-private.hh" 31 #include "hb-utf-private.hh" 32 33 34 #ifndef HB_DEBUG_BUFFER 35 #define HB_DEBUG_BUFFER (HB_DEBUG+0) 36 #endif 37 38 /** 39 * SECTION: hb-buffer 40 * @title: Buffers 41 * @short_description: Input and output buffers 42 * @include: hb.h 43 * 44 * Buffers serve dual role in HarfBuzz; they hold the input characters that are 45 * passed hb_shape(), and after shaping they hold the output glyphs. 46 **/ 47 48 /** 49 * hb_segment_properties_equal: 50 * @a: first #hb_segment_properties_t to compare. 51 * @b: second #hb_segment_properties_t to compare. 52 * 53 * Checks the equality of two #hb_segment_properties_t's. 54 * 55 * Return value: (transfer full): 56 * %true if all properties of @a equal those of @b, false otherwise. 57 * 58 * Since: 0.9.7 59 **/ 60 hb_bool_t 61 hb_segment_properties_equal (const hb_segment_properties_t *a, 62 const hb_segment_properties_t *b) 63 { 64 return a->direction == b->direction && 65 a->script == b->script && 66 a->language == b->language && 67 a->reserved1 == b->reserved1 && 68 a->reserved2 == b->reserved2; 69 70 } 71 72 /** 73 * hb_segment_properties_hash: 74 * @p: #hb_segment_properties_t to hash. 75 * 76 * Creates a hash representing @p. 77 * 78 * Return value: 79 * A hash of @p. 80 * 81 * Since: 0.9.7 82 **/ 83 unsigned int 84 hb_segment_properties_hash (const hb_segment_properties_t *p) 85 { 86 return (unsigned int) p->direction ^ 87 (unsigned int) p->script ^ 88 (intptr_t) (p->language); 89 } 90 91 92 93 /* Here is how the buffer works internally: 94 * 95 * There are two info pointers: info and out_info. They always have 96 * the same allocated size, but different lengths. 97 * 98 * As an optimization, both info and out_info may point to the 99 * same piece of memory, which is owned by info. This remains the 100 * case as long as out_len doesn't exceed i at any time. 101 * In that case, swap_buffers() is no-op and the glyph operations operate 102 * mostly in-place. 103 * 104 * As soon as out_info gets longer than info, out_info is moved over 105 * to an alternate buffer (which we reuse the pos buffer for!), and its 106 * current contents (out_len entries) are copied to the new place. 107 * This should all remain transparent to the user. swap_buffers() then 108 * switches info and out_info. 109 */ 110 111 112 113 /* Internal API */ 114 115 bool 116 hb_buffer_t::enlarge (unsigned int size) 117 { 118 if (unlikely (in_error)) 119 return false; 120 if (unlikely (size > max_len)) 121 { 122 in_error = true; 123 return false; 124 } 125 126 unsigned int new_allocated = allocated; 127 hb_glyph_position_t *new_pos = NULL; 128 hb_glyph_info_t *new_info = NULL; 129 bool separate_out = out_info != info; 130 131 if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) 132 goto done; 133 134 while (size >= new_allocated) 135 new_allocated += (new_allocated >> 1) + 32; 136 137 ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); 138 if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) 139 goto done; 140 141 new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); 142 new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); 143 144 done: 145 if (unlikely (!new_pos || !new_info)) 146 in_error = true; 147 148 if (likely (new_pos)) 149 pos = new_pos; 150 151 if (likely (new_info)) 152 info = new_info; 153 154 out_info = separate_out ? (hb_glyph_info_t *) pos : info; 155 if (likely (!in_error)) 156 allocated = new_allocated; 157 158 return likely (!in_error); 159 } 160 161 bool 162 hb_buffer_t::make_room_for (unsigned int num_in, 163 unsigned int num_out) 164 { 165 if (unlikely (!ensure (out_len + num_out))) return false; 166 167 if (out_info == info && 168 out_len + num_out > idx + num_in) 169 { 170 assert (have_output); 171 172 out_info = (hb_glyph_info_t *) pos; 173 memcpy (out_info, info, out_len * sizeof (out_info[0])); 174 } 175 176 return true; 177 } 178 179 bool 180 hb_buffer_t::shift_forward (unsigned int count) 181 { 182 assert (have_output); 183 if (unlikely (!ensure (len + count))) return false; 184 185 memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0])); 186 len += count; 187 idx += count; 188 189 return true; 190 } 191 192 hb_buffer_t::scratch_buffer_t * 193 hb_buffer_t::get_scratch_buffer (unsigned int *size) 194 { 195 have_output = false; 196 have_positions = false; 197 198 out_len = 0; 199 out_info = info; 200 201 assert ((uintptr_t) pos % sizeof (scratch_buffer_t) == 0); 202 *size = allocated * sizeof (pos[0]) / sizeof (scratch_buffer_t); 203 return (scratch_buffer_t *) (void *) pos; 204 } 205 206 207 208 /* HarfBuzz-Internal API */ 209 210 void 211 hb_buffer_t::reset (void) 212 { 213 if (unlikely (hb_object_is_inert (this))) 214 return; 215 216 hb_unicode_funcs_destroy (unicode); 217 unicode = hb_unicode_funcs_get_default (); 218 flags = HB_BUFFER_FLAG_DEFAULT; 219 replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; 220 221 clear (); 222 } 223 224 void 225 hb_buffer_t::clear (void) 226 { 227 if (unlikely (hb_object_is_inert (this))) 228 return; 229 230 hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; 231 props = default_props; 232 scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; 233 234 content_type = HB_BUFFER_CONTENT_TYPE_INVALID; 235 in_error = false; 236 have_output = false; 237 have_positions = false; 238 239 idx = 0; 240 len = 0; 241 out_len = 0; 242 out_info = info; 243 244 serial = 0; 245 246 memset (context, 0, sizeof context); 247 memset (context_len, 0, sizeof context_len); 248 249 deallocate_var_all (); 250 } 251 252 void 253 hb_buffer_t::add (hb_codepoint_t codepoint, 254 unsigned int cluster) 255 { 256 hb_glyph_info_t *glyph; 257 258 if (unlikely (!ensure (len + 1))) return; 259 260 glyph = &info[len]; 261 262 memset (glyph, 0, sizeof (*glyph)); 263 glyph->codepoint = codepoint; 264 glyph->mask = 1; 265 glyph->cluster = cluster; 266 267 len++; 268 } 269 270 void 271 hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) 272 { 273 if (unlikely (!ensure (len + 1))) return; 274 275 info[len] = glyph_info; 276 277 len++; 278 } 279 280 281 void 282 hb_buffer_t::remove_output (void) 283 { 284 if (unlikely (hb_object_is_inert (this))) 285 return; 286 287 have_output = false; 288 have_positions = false; 289 290 out_len = 0; 291 out_info = info; 292 } 293 294 void 295 hb_buffer_t::clear_output (void) 296 { 297 if (unlikely (hb_object_is_inert (this))) 298 return; 299 300 have_output = true; 301 have_positions = false; 302 303 out_len = 0; 304 out_info = info; 305 } 306 307 void 308 hb_buffer_t::clear_positions (void) 309 { 310 if (unlikely (hb_object_is_inert (this))) 311 return; 312 313 have_output = false; 314 have_positions = true; 315 316 out_len = 0; 317 out_info = info; 318 319 memset (pos, 0, sizeof (pos[0]) * len); 320 } 321 322 void 323 hb_buffer_t::swap_buffers (void) 324 { 325 if (unlikely (in_error)) return; 326 327 assert (have_output); 328 have_output = false; 329 330 if (out_info != info) 331 { 332 hb_glyph_info_t *tmp_string; 333 tmp_string = info; 334 info = out_info; 335 out_info = tmp_string; 336 pos = (hb_glyph_position_t *) out_info; 337 } 338 339 unsigned int tmp; 340 tmp = len; 341 len = out_len; 342 out_len = tmp; 343 344 idx = 0; 345 } 346 347 348 void 349 hb_buffer_t::replace_glyphs (unsigned int num_in, 350 unsigned int num_out, 351 const uint32_t *glyph_data) 352 { 353 if (unlikely (!make_room_for (num_in, num_out))) return; 354 355 merge_clusters (idx, idx + num_in); 356 357 hb_glyph_info_t orig_info = info[idx]; 358 hb_glyph_info_t *pinfo = &out_info[out_len]; 359 for (unsigned int i = 0; i < num_out; i++) 360 { 361 *pinfo = orig_info; 362 pinfo->codepoint = glyph_data[i]; 363 pinfo++; 364 } 365 366 idx += num_in; 367 out_len += num_out; 368 } 369 370 void 371 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) 372 { 373 if (unlikely (!make_room_for (0, 1))) return; 374 375 out_info[out_len] = info[idx]; 376 out_info[out_len].codepoint = glyph_index; 377 378 out_len++; 379 } 380 381 void 382 hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info) 383 { 384 if (unlikely (!make_room_for (0, 1))) return; 385 386 out_info[out_len] = glyph_info; 387 388 out_len++; 389 } 390 391 void 392 hb_buffer_t::copy_glyph (void) 393 { 394 if (unlikely (!make_room_for (0, 1))) return; 395 396 out_info[out_len] = info[idx]; 397 398 out_len++; 399 } 400 401 bool 402 hb_buffer_t::move_to (unsigned int i) 403 { 404 if (!have_output) 405 { 406 assert (i <= len); 407 idx = i; 408 return true; 409 } 410 if (unlikely (in_error)) 411 return false; 412 413 assert (i <= out_len + (len - idx)); 414 415 if (out_len < i) 416 { 417 unsigned int count = i - out_len; 418 if (unlikely (!make_room_for (count, count))) return false; 419 420 memmove (out_info + out_len, info + idx, count * sizeof (out_info[0])); 421 idx += count; 422 out_len += count; 423 } 424 else if (out_len > i) 425 { 426 /* Tricky part: rewinding... */ 427 unsigned int count = out_len - i; 428 429 if (unlikely (idx < count && !shift_forward (count + 32))) return false; 430 431 assert (idx >= count); 432 433 idx -= count; 434 out_len -= count; 435 memmove (info + idx, out_info + out_len, count * sizeof (out_info[0])); 436 } 437 438 return true; 439 } 440 441 void 442 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) 443 { 444 if (unlikely (out_info != info || out_len != idx)) { 445 if (unlikely (!make_room_for (1, 1))) return; 446 out_info[out_len] = info[idx]; 447 } 448 out_info[out_len].codepoint = glyph_index; 449 450 idx++; 451 out_len++; 452 } 453 454 455 void 456 hb_buffer_t::set_masks (hb_mask_t value, 457 hb_mask_t mask, 458 unsigned int cluster_start, 459 unsigned int cluster_end) 460 { 461 hb_mask_t not_mask = ~mask; 462 value &= mask; 463 464 if (!mask) 465 return; 466 467 if (cluster_start == 0 && cluster_end == (unsigned int)-1) { 468 unsigned int count = len; 469 for (unsigned int i = 0; i < count; i++) 470 info[i].mask = (info[i].mask & not_mask) | value; 471 return; 472 } 473 474 unsigned int count = len; 475 for (unsigned int i = 0; i < count; i++) 476 if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) 477 info[i].mask = (info[i].mask & not_mask) | value; 478 } 479 480 void 481 hb_buffer_t::reverse_range (unsigned int start, 482 unsigned int end) 483 { 484 unsigned int i, j; 485 486 if (end - start < 2) 487 return; 488 489 for (i = start, j = end - 1; i < j; i++, j--) { 490 hb_glyph_info_t t; 491 492 t = info[i]; 493 info[i] = info[j]; 494 info[j] = t; 495 } 496 497 if (have_positions) { 498 for (i = start, j = end - 1; i < j; i++, j--) { 499 hb_glyph_position_t t; 500 501 t = pos[i]; 502 pos[i] = pos[j]; 503 pos[j] = t; 504 } 505 } 506 } 507 508 void 509 hb_buffer_t::reverse (void) 510 { 511 if (unlikely (!len)) 512 return; 513 514 reverse_range (0, len); 515 } 516 517 void 518 hb_buffer_t::reverse_clusters (void) 519 { 520 unsigned int i, start, count, last_cluster; 521 522 if (unlikely (!len)) 523 return; 524 525 reverse (); 526 527 count = len; 528 start = 0; 529 last_cluster = info[0].cluster; 530 for (i = 1; i < count; i++) { 531 if (last_cluster != info[i].cluster) { 532 reverse_range (start, i); 533 start = i; 534 last_cluster = info[i].cluster; 535 } 536 } 537 reverse_range (start, i); 538 } 539 540 void 541 hb_buffer_t::merge_clusters_impl (unsigned int start, 542 unsigned int end) 543 { 544 if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) 545 return; 546 547 unsigned int cluster = info[start].cluster; 548 549 for (unsigned int i = start + 1; i < end; i++) 550 cluster = MIN (cluster, info[i].cluster); 551 552 /* Extend end */ 553 while (end < len && info[end - 1].cluster == info[end].cluster) 554 end++; 555 556 /* Extend start */ 557 while (idx < start && info[start - 1].cluster == info[start].cluster) 558 start--; 559 560 /* If we hit the start of buffer, continue in out-buffer. */ 561 if (idx == start) 562 for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) 563 out_info[i - 1].cluster = cluster; 564 565 for (unsigned int i = start; i < end; i++) 566 info[i].cluster = cluster; 567 } 568 void 569 hb_buffer_t::merge_out_clusters (unsigned int start, 570 unsigned int end) 571 { 572 if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) 573 return; 574 575 if (unlikely (end - start < 2)) 576 return; 577 578 unsigned int cluster = out_info[start].cluster; 579 580 for (unsigned int i = start + 1; i < end; i++) 581 cluster = MIN (cluster, out_info[i].cluster); 582 583 /* Extend start */ 584 while (start && out_info[start - 1].cluster == out_info[start].cluster) 585 start--; 586 587 /* Extend end */ 588 while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster) 589 end++; 590 591 /* If we hit the end of out-buffer, continue in buffer. */ 592 if (end == out_len) 593 for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) 594 info[i].cluster = cluster; 595 596 for (unsigned int i = start; i < end; i++) 597 out_info[i].cluster = cluster; 598 } 599 void 600 hb_buffer_t::delete_glyph () 601 { 602 unsigned int cluster = info[idx].cluster; 603 if (idx + 1 < len && cluster == info[idx + 1].cluster) 604 { 605 /* Cluster survives; do nothing. */ 606 goto done; 607 } 608 609 if (out_len) 610 { 611 /* Merge cluster backward. */ 612 if (cluster < out_info[out_len - 1].cluster) 613 { 614 unsigned int old_cluster = out_info[out_len - 1].cluster; 615 for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) 616 out_info[i - 1].cluster = cluster; 617 } 618 goto done; 619 } 620 621 if (idx + 1 < len) 622 { 623 /* Merge cluster forward. */ 624 merge_clusters (idx, idx + 2); 625 goto done; 626 } 627 628 done: 629 skip_glyph (); 630 } 631 632 void 633 hb_buffer_t::guess_segment_properties (void) 634 { 635 assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || 636 (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); 637 638 /* If script is set to INVALID, guess from buffer contents */ 639 if (props.script == HB_SCRIPT_INVALID) { 640 for (unsigned int i = 0; i < len; i++) { 641 hb_script_t script = unicode->script (info[i].codepoint); 642 if (likely (script != HB_SCRIPT_COMMON && 643 script != HB_SCRIPT_INHERITED && 644 script != HB_SCRIPT_UNKNOWN)) { 645 props.script = script; 646 break; 647 } 648 } 649 } 650 651 /* If direction is set to INVALID, guess from script */ 652 if (props.direction == HB_DIRECTION_INVALID) { 653 props.direction = hb_script_get_horizontal_direction (props.script); 654 } 655 656 /* If language is not set, use default language from locale */ 657 if (props.language == HB_LANGUAGE_INVALID) { 658 /* TODO get_default_for_script? using $LANGUAGE */ 659 props.language = hb_language_get_default (); 660 } 661 } 662 663 664 /* Public API */ 665 666 /** 667 * hb_buffer_create: (Xconstructor) 668 * 669 * Creates a new #hb_buffer_t with all properties to defaults. 670 * 671 * Return value: (transfer full): 672 * A newly allocated #hb_buffer_t with a reference count of 1. The initial 673 * reference count should be released with hb_buffer_destroy() when you are done 674 * using the #hb_buffer_t. This function never returns %NULL. If memory cannot 675 * be allocated, a special #hb_buffer_t object will be returned on which 676 * hb_buffer_allocation_successful() returns %false. 677 * 678 * Since: 0.9.2 679 **/ 680 hb_buffer_t * 681 hb_buffer_create (void) 682 { 683 hb_buffer_t *buffer; 684 685 if (!(buffer = hb_object_create<hb_buffer_t> ())) 686 return hb_buffer_get_empty (); 687 688 buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; 689 690 buffer->reset (); 691 692 return buffer; 693 } 694 695 /** 696 * hb_buffer_get_empty: 697 * 698 * 699 * 700 * Return value: (transfer full): 701 * 702 * Since: 0.9.2 703 **/ 704 hb_buffer_t * 705 hb_buffer_get_empty (void) 706 { 707 static const hb_buffer_t _hb_buffer_nil = { 708 HB_OBJECT_HEADER_STATIC, 709 710 const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil), 711 HB_BUFFER_FLAG_DEFAULT, 712 HB_BUFFER_CLUSTER_LEVEL_DEFAULT, 713 HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 714 HB_BUFFER_SCRATCH_FLAG_DEFAULT, 715 HB_BUFFER_MAX_LEN_DEFAULT, 716 717 HB_BUFFER_CONTENT_TYPE_INVALID, 718 HB_SEGMENT_PROPERTIES_DEFAULT, 719 true, /* in_error */ 720 true, /* have_output */ 721 true /* have_positions */ 722 723 /* Zero is good enough for everything else. */ 724 }; 725 726 return const_cast<hb_buffer_t *> (&_hb_buffer_nil); 727 } 728 729 /** 730 * hb_buffer_reference: (skip) 731 * @buffer: an #hb_buffer_t. 732 * 733 * Increases the reference count on @buffer by one. This prevents @buffer from 734 * being destroyed until a matching call to hb_buffer_destroy() is made. 735 * 736 * Return value: (transfer full): 737 * The referenced #hb_buffer_t. 738 * 739 * Since: 0.9.2 740 **/ 741 hb_buffer_t * 742 hb_buffer_reference (hb_buffer_t *buffer) 743 { 744 return hb_object_reference (buffer); 745 } 746 747 /** 748 * hb_buffer_destroy: (skip) 749 * @buffer: an #hb_buffer_t. 750 * 751 * Deallocate the @buffer. 752 * Decreases the reference count on @buffer by one. If the result is zero, then 753 * @buffer and all associated resources are freed. See hb_buffer_reference(). 754 * 755 * Since: 0.9.2 756 **/ 757 void 758 hb_buffer_destroy (hb_buffer_t *buffer) 759 { 760 if (!hb_object_destroy (buffer)) return; 761 762 hb_unicode_funcs_destroy (buffer->unicode); 763 764 free (buffer->info); 765 free (buffer->pos); 766 if (buffer->message_destroy) 767 buffer->message_destroy (buffer->message_data); 768 769 free (buffer); 770 } 771 772 /** 773 * hb_buffer_set_user_data: (skip) 774 * @buffer: an #hb_buffer_t. 775 * @key: 776 * @data: 777 * @destroy: 778 * @replace: 779 * 780 * 781 * 782 * Return value: 783 * 784 * Since: 0.9.2 785 **/ 786 hb_bool_t 787 hb_buffer_set_user_data (hb_buffer_t *buffer, 788 hb_user_data_key_t *key, 789 void * data, 790 hb_destroy_func_t destroy, 791 hb_bool_t replace) 792 { 793 return hb_object_set_user_data (buffer, key, data, destroy, replace); 794 } 795 796 /** 797 * hb_buffer_get_user_data: (skip) 798 * @buffer: an #hb_buffer_t. 799 * @key: 800 * 801 * 802 * 803 * Return value: 804 * 805 * Since: 0.9.2 806 **/ 807 void * 808 hb_buffer_get_user_data (hb_buffer_t *buffer, 809 hb_user_data_key_t *key) 810 { 811 return hb_object_get_user_data (buffer, key); 812 } 813 814 815 /** 816 * hb_buffer_set_content_type: 817 * @buffer: an #hb_buffer_t. 818 * @content_type: the type of buffer contents to set 819 * 820 * Sets the type of @buffer contents, buffers are either empty, contain 821 * characters (before shaping) or glyphs (the result of shaping). 822 * 823 * Since: 0.9.5 824 **/ 825 void 826 hb_buffer_set_content_type (hb_buffer_t *buffer, 827 hb_buffer_content_type_t content_type) 828 { 829 buffer->content_type = content_type; 830 } 831 832 /** 833 * hb_buffer_get_content_type: 834 * @buffer: an #hb_buffer_t. 835 * 836 * see hb_buffer_set_content_type(). 837 * 838 * Return value: 839 * The type of @buffer contents. 840 * 841 * Since: 0.9.5 842 **/ 843 hb_buffer_content_type_t 844 hb_buffer_get_content_type (hb_buffer_t *buffer) 845 { 846 return buffer->content_type; 847 } 848 849 850 /** 851 * hb_buffer_set_unicode_funcs: 852 * @buffer: an #hb_buffer_t. 853 * @unicode_funcs: 854 * 855 * 856 * 857 * Since: 0.9.2 858 **/ 859 void 860 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, 861 hb_unicode_funcs_t *unicode_funcs) 862 { 863 if (unlikely (hb_object_is_inert (buffer))) 864 return; 865 866 if (!unicode_funcs) 867 unicode_funcs = hb_unicode_funcs_get_default (); 868 869 870 hb_unicode_funcs_reference (unicode_funcs); 871 hb_unicode_funcs_destroy (buffer->unicode); 872 buffer->unicode = unicode_funcs; 873 } 874 875 /** 876 * hb_buffer_get_unicode_funcs: 877 * @buffer: an #hb_buffer_t. 878 * 879 * 880 * 881 * Return value: 882 * 883 * Since: 0.9.2 884 **/ 885 hb_unicode_funcs_t * 886 hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) 887 { 888 return buffer->unicode; 889 } 890 891 /** 892 * hb_buffer_set_direction: 893 * @buffer: an #hb_buffer_t. 894 * @direction: the #hb_direction_t of the @buffer 895 * 896 * Set the text flow direction of the buffer. No shaping can happen without 897 * setting @buffer direction, and it controls the visual direction for the 898 * output glyphs; for RTL direction the glyphs will be reversed. Many layout 899 * features depend on the proper setting of the direction, for example, 900 * reversing RTL text before shaping, then shaping with LTR direction is not 901 * the same as keeping the text in logical order and shaping with RTL 902 * direction. 903 * 904 * Since: 0.9.2 905 **/ 906 void 907 hb_buffer_set_direction (hb_buffer_t *buffer, 908 hb_direction_t direction) 909 910 { 911 if (unlikely (hb_object_is_inert (buffer))) 912 return; 913 914 buffer->props.direction = direction; 915 } 916 917 /** 918 * hb_buffer_get_direction: 919 * @buffer: an #hb_buffer_t. 920 * 921 * See hb_buffer_set_direction() 922 * 923 * Return value: 924 * The direction of the @buffer. 925 * 926 * Since: 0.9.2 927 **/ 928 hb_direction_t 929 hb_buffer_get_direction (hb_buffer_t *buffer) 930 { 931 return buffer->props.direction; 932 } 933 934 /** 935 * hb_buffer_set_script: 936 * @buffer: an #hb_buffer_t. 937 * @script: an #hb_script_t to set. 938 * 939 * Sets the script of @buffer to @script. 940 * 941 * Script is crucial for choosing the proper shaping behaviour for scripts that 942 * require it (e.g. Arabic) and the which OpenType features defined in the font 943 * to be applied. 944 * 945 * You can pass one of the predefined #hb_script_t values, or use 946 * hb_script_from_string() or hb_script_from_iso15924_tag() to get the 947 * corresponding script from an ISO15924 script tag. 948 * 949 * Since: 0.9.2 950 **/ 951 void 952 hb_buffer_set_script (hb_buffer_t *buffer, 953 hb_script_t script) 954 { 955 if (unlikely (hb_object_is_inert (buffer))) 956 return; 957 958 buffer->props.script = script; 959 } 960 961 /** 962 * hb_buffer_get_script: 963 * @buffer: an #hb_buffer_t. 964 * 965 * See hb_buffer_set_script(). 966 * 967 * Return value: 968 * The #hb_script_t of the @buffer. 969 * 970 * Since: 0.9.2 971 **/ 972 hb_script_t 973 hb_buffer_get_script (hb_buffer_t *buffer) 974 { 975 return buffer->props.script; 976 } 977 978 /** 979 * hb_buffer_set_language: 980 * @buffer: an #hb_buffer_t. 981 * @language: an hb_language_t to set. 982 * 983 * Sets the language of @buffer to @language. 984 * 985 * Languages are crucial for selecting which OpenType feature to apply to the 986 * buffer which can result in applying language-specific behaviour. Languages 987 * are orthogonal to the scripts, and though they are related, they are 988 * different concepts and should not be confused with each other. 989 * 990 * Use hb_language_from_string() to convert from ISO639 language codes to 991 * #hb_language_t. 992 * 993 * Since: 0.9.2 994 **/ 995 void 996 hb_buffer_set_language (hb_buffer_t *buffer, 997 hb_language_t language) 998 { 999 if (unlikely (hb_object_is_inert (buffer))) 1000 return; 1001 1002 buffer->props.language = language; 1003 } 1004 1005 /** 1006 * hb_buffer_get_language: 1007 * @buffer: an #hb_buffer_t. 1008 * 1009 * See hb_buffer_set_language(). 1010 * 1011 * Return value: (transfer none): 1012 * The #hb_language_t of the buffer. Must not be freed by the caller. 1013 * 1014 * Since: 0.9.2 1015 **/ 1016 hb_language_t 1017 hb_buffer_get_language (hb_buffer_t *buffer) 1018 { 1019 return buffer->props.language; 1020 } 1021 1022 /** 1023 * hb_buffer_set_segment_properties: 1024 * @buffer: an #hb_buffer_t. 1025 * @props: an #hb_segment_properties_t to use. 1026 * 1027 * Sets the segment properties of the buffer, a shortcut for calling 1028 * hb_buffer_set_direction(), hb_buffer_set_script() and 1029 * hb_buffer_set_language() individually. 1030 * 1031 * Since: 0.9.7 1032 **/ 1033 void 1034 hb_buffer_set_segment_properties (hb_buffer_t *buffer, 1035 const hb_segment_properties_t *props) 1036 { 1037 if (unlikely (hb_object_is_inert (buffer))) 1038 return; 1039 1040 buffer->props = *props; 1041 } 1042 1043 /** 1044 * hb_buffer_get_segment_properties: 1045 * @buffer: an #hb_buffer_t. 1046 * @props: (out): the output #hb_segment_properties_t. 1047 * 1048 * Sets @props to the #hb_segment_properties_t of @buffer. 1049 * 1050 * Since: 0.9.7 1051 **/ 1052 void 1053 hb_buffer_get_segment_properties (hb_buffer_t *buffer, 1054 hb_segment_properties_t *props) 1055 { 1056 *props = buffer->props; 1057 } 1058 1059 1060 /** 1061 * hb_buffer_set_flags: 1062 * @buffer: an #hb_buffer_t. 1063 * @flags: the buffer flags to set. 1064 * 1065 * Sets @buffer flags to @flags. See #hb_buffer_flags_t. 1066 * 1067 * Since: 0.9.7 1068 **/ 1069 void 1070 hb_buffer_set_flags (hb_buffer_t *buffer, 1071 hb_buffer_flags_t flags) 1072 { 1073 if (unlikely (hb_object_is_inert (buffer))) 1074 return; 1075 1076 buffer->flags = flags; 1077 } 1078 1079 /** 1080 * hb_buffer_get_flags: 1081 * @buffer: an #hb_buffer_t. 1082 * 1083 * See hb_buffer_set_flags(). 1084 * 1085 * Return value: 1086 * The @buffer flags. 1087 * 1088 * Since: 0.9.7 1089 **/ 1090 hb_buffer_flags_t 1091 hb_buffer_get_flags (hb_buffer_t *buffer) 1092 { 1093 return buffer->flags; 1094 } 1095 1096 /** 1097 * hb_buffer_set_cluster_level: 1098 * @buffer: an #hb_buffer_t. 1099 * @cluster_level: 1100 * 1101 * 1102 * 1103 * Since: 0.9.42 1104 **/ 1105 void 1106 hb_buffer_set_cluster_level (hb_buffer_t *buffer, 1107 hb_buffer_cluster_level_t cluster_level) 1108 { 1109 if (unlikely (hb_object_is_inert (buffer))) 1110 return; 1111 1112 buffer->cluster_level = cluster_level; 1113 } 1114 1115 /** 1116 * hb_buffer_get_cluster_level: 1117 * @buffer: an #hb_buffer_t. 1118 * 1119 * 1120 * 1121 * Return value: 1122 * 1123 * Since: 0.9.42 1124 **/ 1125 hb_buffer_cluster_level_t 1126 hb_buffer_get_cluster_level (hb_buffer_t *buffer) 1127 { 1128 return buffer->cluster_level; 1129 } 1130 1131 1132 /** 1133 * hb_buffer_set_replacement_codepoint: 1134 * @buffer: an #hb_buffer_t. 1135 * @replacement: the replacement #hb_codepoint_t 1136 * 1137 * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding 1138 * when adding text to @buffer. 1139 * 1140 * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. 1141 * 1142 * Since: 0.9.31 1143 **/ 1144 void 1145 hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, 1146 hb_codepoint_t replacement) 1147 { 1148 if (unlikely (hb_object_is_inert (buffer))) 1149 return; 1150 1151 buffer->replacement = replacement; 1152 } 1153 1154 /** 1155 * hb_buffer_get_replacement_codepoint: 1156 * @buffer: an #hb_buffer_t. 1157 * 1158 * See hb_buffer_set_replacement_codepoint(). 1159 * 1160 * Return value: 1161 * The @buffer replacement #hb_codepoint_t. 1162 * 1163 * Since: 0.9.31 1164 **/ 1165 hb_codepoint_t 1166 hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) 1167 { 1168 return buffer->replacement; 1169 } 1170 1171 1172 /** 1173 * hb_buffer_reset: 1174 * @buffer: an #hb_buffer_t. 1175 * 1176 * Resets the buffer to its initial status, as if it was just newly created 1177 * with hb_buffer_create(). 1178 * 1179 * Since: 0.9.2 1180 **/ 1181 void 1182 hb_buffer_reset (hb_buffer_t *buffer) 1183 { 1184 buffer->reset (); 1185 } 1186 1187 /** 1188 * hb_buffer_clear_contents: 1189 * @buffer: an #hb_buffer_t. 1190 * 1191 * Similar to hb_buffer_reset(), but does not clear the Unicode functions and 1192 * the replacement code point. 1193 * 1194 * Since: 0.9.11 1195 **/ 1196 void 1197 hb_buffer_clear_contents (hb_buffer_t *buffer) 1198 { 1199 buffer->clear (); 1200 } 1201 1202 /** 1203 * hb_buffer_pre_allocate: 1204 * @buffer: an #hb_buffer_t. 1205 * @size: number of items to pre allocate. 1206 * 1207 * Pre allocates memory for @buffer to fit at least @size number of items. 1208 * 1209 * Return value: 1210 * %true if @buffer memory allocation succeeded, %false otherwise. 1211 * 1212 * Since: 0.9.2 1213 **/ 1214 hb_bool_t 1215 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) 1216 { 1217 return buffer->ensure (size); 1218 } 1219 1220 /** 1221 * hb_buffer_allocation_successful: 1222 * @buffer: an #hb_buffer_t. 1223 * 1224 * Check if allocating memory for the buffer succeeded. 1225 * 1226 * Return value: 1227 * %true if @buffer memory allocation succeeded, %false otherwise. 1228 * 1229 * Since: 0.9.2 1230 **/ 1231 hb_bool_t 1232 hb_buffer_allocation_successful (hb_buffer_t *buffer) 1233 { 1234 return !buffer->in_error; 1235 } 1236 1237 /** 1238 * hb_buffer_add: 1239 * @buffer: an #hb_buffer_t. 1240 * @codepoint: a Unicode code point. 1241 * @cluster: the cluster value of @codepoint. 1242 * 1243 * Appends a character with the Unicode value of @codepoint to @buffer, and 1244 * gives it the initial cluster value of @cluster. Clusters can be any thing 1245 * the client wants, they are usually used to refer to the index of the 1246 * character in the input text stream and are output in 1247 * #hb_glyph_info_t.cluster field. 1248 * 1249 * This function does not check the validity of @codepoint, it is up to the 1250 * caller to ensure it is a valid Unicode code point. 1251 * 1252 * Since: 0.9.7 1253 **/ 1254 void 1255 hb_buffer_add (hb_buffer_t *buffer, 1256 hb_codepoint_t codepoint, 1257 unsigned int cluster) 1258 { 1259 buffer->add (codepoint, cluster); 1260 buffer->clear_context (1); 1261 } 1262 1263 /** 1264 * hb_buffer_set_length: 1265 * @buffer: an #hb_buffer_t. 1266 * @length: the new length of @buffer. 1267 * 1268 * Similar to hb_buffer_pre_allocate(), but clears any new items added at the 1269 * end. 1270 * 1271 * Return value: 1272 * %true if @buffer memory allocation succeeded, %false otherwise. 1273 * 1274 * Since: 0.9.2 1275 **/ 1276 hb_bool_t 1277 hb_buffer_set_length (hb_buffer_t *buffer, 1278 unsigned int length) 1279 { 1280 if (unlikely (hb_object_is_inert (buffer))) 1281 return length == 0; 1282 1283 if (!buffer->ensure (length)) 1284 return false; 1285 1286 /* Wipe the new space */ 1287 if (length > buffer->len) { 1288 memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); 1289 if (buffer->have_positions) 1290 memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); 1291 } 1292 1293 buffer->len = length; 1294 1295 if (!length) 1296 { 1297 buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID; 1298 buffer->clear_context (0); 1299 } 1300 buffer->clear_context (1); 1301 1302 return true; 1303 } 1304 1305 /** 1306 * hb_buffer_get_length: 1307 * @buffer: an #hb_buffer_t. 1308 * 1309 * Returns the number of items in the buffer. 1310 * 1311 * Return value: 1312 * The @buffer length. 1313 * The value valid as long as buffer has not been modified. 1314 * 1315 * Since: 0.9.2 1316 **/ 1317 unsigned int 1318 hb_buffer_get_length (hb_buffer_t *buffer) 1319 { 1320 return buffer->len; 1321 } 1322 1323 /** 1324 * hb_buffer_get_glyph_infos: 1325 * @buffer: an #hb_buffer_t. 1326 * @length: (out): output array length. 1327 * 1328 * Returns @buffer glyph information array. Returned pointer 1329 * is valid as long as @buffer contents are not modified. 1330 * 1331 * Return value: (transfer none) (array length=length): 1332 * The @buffer glyph information array. 1333 * The value valid as long as buffer has not been modified. 1334 * 1335 * Since: 0.9.2 1336 **/ 1337 hb_glyph_info_t * 1338 hb_buffer_get_glyph_infos (hb_buffer_t *buffer, 1339 unsigned int *length) 1340 { 1341 if (length) 1342 *length = buffer->len; 1343 1344 return (hb_glyph_info_t *) buffer->info; 1345 } 1346 1347 /** 1348 * hb_buffer_get_glyph_positions: 1349 * @buffer: an #hb_buffer_t. 1350 * @length: (out): output length. 1351 * 1352 * Returns @buffer glyph position array. Returned pointer 1353 * is valid as long as @buffer contents are not modified. 1354 * 1355 * Return value: (transfer none) (array length=length): 1356 * The @buffer glyph position array. 1357 * The value valid as long as buffer has not been modified. 1358 * 1359 * Since: 0.9.2 1360 **/ 1361 hb_glyph_position_t * 1362 hb_buffer_get_glyph_positions (hb_buffer_t *buffer, 1363 unsigned int *length) 1364 { 1365 if (!buffer->have_positions) 1366 buffer->clear_positions (); 1367 1368 if (length) 1369 *length = buffer->len; 1370 1371 return (hb_glyph_position_t *) buffer->pos; 1372 } 1373 1374 /** 1375 * hb_buffer_reverse: 1376 * @buffer: an #hb_buffer_t. 1377 * 1378 * Reverses buffer contents. 1379 * 1380 * Since: 0.9.2 1381 **/ 1382 void 1383 hb_buffer_reverse (hb_buffer_t *buffer) 1384 { 1385 buffer->reverse (); 1386 } 1387 1388 /** 1389 * hb_buffer_reverse_range: 1390 * @buffer: an #hb_buffer_t. 1391 * @start: start index. 1392 * @end: end index. 1393 * 1394 * Reverses buffer contents between start to end. 1395 * 1396 * Since: 0.9.41 1397 **/ 1398 void 1399 hb_buffer_reverse_range (hb_buffer_t *buffer, 1400 unsigned int start, unsigned int end) 1401 { 1402 buffer->reverse_range (start, end); 1403 } 1404 1405 /** 1406 * hb_buffer_reverse_clusters: 1407 * @buffer: an #hb_buffer_t. 1408 * 1409 * Reverses buffer clusters. That is, the buffer contents are 1410 * reversed, then each cluster (consecutive items having the 1411 * same cluster number) are reversed again. 1412 * 1413 * Since: 0.9.2 1414 **/ 1415 void 1416 hb_buffer_reverse_clusters (hb_buffer_t *buffer) 1417 { 1418 buffer->reverse_clusters (); 1419 } 1420 1421 /** 1422 * hb_buffer_guess_segment_properties: 1423 * @buffer: an #hb_buffer_t. 1424 * 1425 * Sets unset buffer segment properties based on buffer Unicode 1426 * contents. If buffer is not empty, it must have content type 1427 * %HB_BUFFER_CONTENT_TYPE_UNICODE. 1428 * 1429 * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it 1430 * will be set to the Unicode script of the first character in 1431 * the buffer that has a script other than %HB_SCRIPT_COMMON, 1432 * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN. 1433 * 1434 * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID), 1435 * it will be set to the natural horizontal direction of the 1436 * buffer script as returned by hb_script_get_horizontal_direction(). 1437 * 1438 * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID), 1439 * it will be set to the process's default language as returned by 1440 * hb_language_get_default(). This may change in the future by 1441 * taking buffer script into consideration when choosing a language. 1442 * 1443 * Since: 0.9.7 1444 **/ 1445 void 1446 hb_buffer_guess_segment_properties (hb_buffer_t *buffer) 1447 { 1448 buffer->guess_segment_properties (); 1449 } 1450 1451 template <typename utf_t> 1452 static inline void 1453 hb_buffer_add_utf (hb_buffer_t *buffer, 1454 const typename utf_t::codepoint_t *text, 1455 int text_length, 1456 unsigned int item_offset, 1457 int item_length) 1458 { 1459 typedef typename utf_t::codepoint_t T; 1460 const hb_codepoint_t replacement = buffer->replacement; 1461 1462 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || 1463 (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); 1464 1465 if (unlikely (hb_object_is_inert (buffer))) 1466 return; 1467 1468 if (text_length == -1) 1469 text_length = utf_t::strlen (text); 1470 1471 if (item_length == -1) 1472 item_length = text_length - item_offset; 1473 1474 buffer->ensure (buffer->len + item_length * sizeof (T) / 4); 1475 1476 /* If buffer is empty and pre-context provided, install it. 1477 * This check is written this way, to make sure people can 1478 * provide pre-context in one add_utf() call, then provide 1479 * text in a follow-up call. See: 1480 * 1481 * https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13 1482 */ 1483 if (!buffer->len && item_offset > 0) 1484 { 1485 /* Add pre-context */ 1486 buffer->clear_context (0); 1487 const T *prev = text + item_offset; 1488 const T *start = text; 1489 while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH) 1490 { 1491 hb_codepoint_t u; 1492 prev = utf_t::prev (prev, start, &u, replacement); 1493 buffer->context[0][buffer->context_len[0]++] = u; 1494 } 1495 } 1496 1497 const T *next = text + item_offset; 1498 const T *end = next + item_length; 1499 while (next < end) 1500 { 1501 hb_codepoint_t u; 1502 const T *old_next = next; 1503 next = utf_t::next (next, end, &u, replacement); 1504 buffer->add (u, old_next - (const T *) text); 1505 } 1506 1507 /* Add post-context */ 1508 buffer->clear_context (1); 1509 end = text + text_length; 1510 while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH) 1511 { 1512 hb_codepoint_t u; 1513 next = utf_t::next (next, end, &u, replacement); 1514 buffer->context[1][buffer->context_len[1]++] = u; 1515 } 1516 1517 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; 1518 } 1519 1520 /** 1521 * hb_buffer_add_utf8: 1522 * @buffer: an #hb_buffer_t. 1523 * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 1524 * characters to append. 1525 * @text_length: the length of the @text, or -1 if it is %NULL terminated. 1526 * @item_offset: the offset of the first character to add to the @buffer. 1527 * @item_length: the number of characters to add to the @buffer, or -1 for the 1528 * end of @text (assuming it is %NULL terminated). 1529 * 1530 * See hb_buffer_add_codepoints(). 1531 * 1532 * Replaces invalid UTF-8 characters with the @buffer replacement code point, 1533 * see hb_buffer_set_replacement_codepoint(). 1534 * 1535 * Since: 0.9.2 1536 **/ 1537 void 1538 hb_buffer_add_utf8 (hb_buffer_t *buffer, 1539 const char *text, 1540 int text_length, 1541 unsigned int item_offset, 1542 int item_length) 1543 { 1544 hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length); 1545 } 1546 1547 /** 1548 * hb_buffer_add_utf16: 1549 * @buffer: an #hb_buffer_t. 1550 * @text: (array length=text_length): an array of UTF-16 characters to append. 1551 * @text_length: the length of the @text, or -1 if it is %NULL terminated. 1552 * @item_offset: the offset of the first character to add to the @buffer. 1553 * @item_length: the number of characters to add to the @buffer, or -1 for the 1554 * end of @text (assuming it is %NULL terminated). 1555 * 1556 * See hb_buffer_add_codepoints(). 1557 * 1558 * Replaces invalid UTF-16 characters with the @buffer replacement code point, 1559 * see hb_buffer_set_replacement_codepoint(). 1560 * 1561 * Since: 0.9.2 1562 **/ 1563 void 1564 hb_buffer_add_utf16 (hb_buffer_t *buffer, 1565 const uint16_t *text, 1566 int text_length, 1567 unsigned int item_offset, 1568 int item_length) 1569 { 1570 hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length); 1571 } 1572 1573 /** 1574 * hb_buffer_add_utf32: 1575 * @buffer: an #hb_buffer_t. 1576 * @text: (array length=text_length): an array of UTF-32 characters to append. 1577 * @text_length: the length of the @text, or -1 if it is %NULL terminated. 1578 * @item_offset: the offset of the first character to add to the @buffer. 1579 * @item_length: the number of characters to add to the @buffer, or -1 for the 1580 * end of @text (assuming it is %NULL terminated). 1581 * 1582 * See hb_buffer_add_codepoints(). 1583 * 1584 * Replaces invalid UTF-32 characters with the @buffer replacement code point, 1585 * see hb_buffer_set_replacement_codepoint(). 1586 * 1587 * Since: 0.9.2 1588 **/ 1589 void 1590 hb_buffer_add_utf32 (hb_buffer_t *buffer, 1591 const uint32_t *text, 1592 int text_length, 1593 unsigned int item_offset, 1594 int item_length) 1595 { 1596 hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length); 1597 } 1598 1599 /** 1600 * hb_buffer_add_latin1: 1601 * @buffer: an #hb_buffer_t. 1602 * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 1603 * characters to append. 1604 * @text_length: the length of the @text, or -1 if it is %NULL terminated. 1605 * @item_offset: the offset of the first character to add to the @buffer. 1606 * @item_length: the number of characters to add to the @buffer, or -1 for the 1607 * end of @text (assuming it is %NULL terminated). 1608 * 1609 * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 1610 * Unicode code points that can fit in 8-bit strings. 1611 * 1612 * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note> 1613 * 1614 * Since: 0.9.39 1615 **/ 1616 void 1617 hb_buffer_add_latin1 (hb_buffer_t *buffer, 1618 const uint8_t *text, 1619 int text_length, 1620 unsigned int item_offset, 1621 int item_length) 1622 { 1623 hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length); 1624 } 1625 1626 /** 1627 * hb_buffer_add_codepoints: 1628 * @buffer: a #hb_buffer_t to append characters to. 1629 * @text: (array length=text_length): an array of Unicode code points to append. 1630 * @text_length: the length of the @text, or -1 if it is %NULL terminated. 1631 * @item_offset: the offset of the first code point to add to the @buffer. 1632 * @item_length: the number of code points to add to the @buffer, or -1 for the 1633 * end of @text (assuming it is %NULL terminated). 1634 * 1635 * Appends characters from @text array to @buffer. The @item_offset is the 1636 * position of the first character from @text that will be appended, and 1637 * @item_length is the number of character. When shaping part of a larger text 1638 * (e.g. a run of text from a paragraph), instead of passing just the substring 1639 * corresponding to the run, it is preferable to pass the whole 1640 * paragraph and specify the run start and length as @item_offset and 1641 * @item_length, respectively, to give HarfBuzz the full context to be able, 1642 * for example, to do cross-run Arabic shaping or properly handle combining 1643 * marks at stat of run. 1644 * 1645 * This function does not check the validity of @text, it is up to the caller 1646 * to ensure it contains a valid Unicode code points. 1647 * 1648 * Since: 0.9.31 1649 **/ 1650 void 1651 hb_buffer_add_codepoints (hb_buffer_t *buffer, 1652 const hb_codepoint_t *text, 1653 int text_length, 1654 unsigned int item_offset, 1655 int item_length) 1656 { 1657 hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length); 1658 } 1659 1660 1661 static int 1662 compare_info_codepoint (const hb_glyph_info_t *pa, 1663 const hb_glyph_info_t *pb) 1664 { 1665 return (int) pb->codepoint - (int) pa->codepoint; 1666 } 1667 1668 static inline void 1669 normalize_glyphs_cluster (hb_buffer_t *buffer, 1670 unsigned int start, 1671 unsigned int end, 1672 bool backward) 1673 { 1674 hb_glyph_position_t *pos = buffer->pos; 1675 1676 /* Total cluster advance */ 1677 hb_position_t total_x_advance = 0, total_y_advance = 0; 1678 for (unsigned int i = start; i < end; i++) 1679 { 1680 total_x_advance += pos[i].x_advance; 1681 total_y_advance += pos[i].y_advance; 1682 } 1683 1684 hb_position_t x_advance = 0, y_advance = 0; 1685 for (unsigned int i = start; i < end; i++) 1686 { 1687 pos[i].x_offset += x_advance; 1688 pos[i].y_offset += y_advance; 1689 1690 x_advance += pos[i].x_advance; 1691 y_advance += pos[i].y_advance; 1692 1693 pos[i].x_advance = 0; 1694 pos[i].y_advance = 0; 1695 } 1696 1697 if (backward) 1698 { 1699 /* Transfer all cluster advance to the last glyph. */ 1700 pos[end - 1].x_advance = total_x_advance; 1701 pos[end - 1].y_advance = total_y_advance; 1702 1703 hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); 1704 } else { 1705 /* Transfer all cluster advance to the first glyph. */ 1706 pos[start].x_advance += total_x_advance; 1707 pos[start].y_advance += total_y_advance; 1708 for (unsigned int i = start + 1; i < end; i++) { 1709 pos[i].x_offset -= total_x_advance; 1710 pos[i].y_offset -= total_y_advance; 1711 } 1712 hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); 1713 } 1714 } 1715 1716 /** 1717 * hb_buffer_normalize_glyphs: 1718 * @buffer: an #hb_buffer_t. 1719 * 1720 * Reorders a glyph buffer to have canonical in-cluster glyph order / position. 1721 * The resulting clusters should behave identical to pre-reordering clusters. 1722 * 1723 * <note>This has nothing to do with Unicode normalization.</note> 1724 * 1725 * Since: 0.9.2 1726 **/ 1727 void 1728 hb_buffer_normalize_glyphs (hb_buffer_t *buffer) 1729 { 1730 assert (buffer->have_positions); 1731 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); 1732 1733 bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); 1734 1735 unsigned int count = buffer->len; 1736 if (unlikely (!count)) return; 1737 hb_glyph_info_t *info = buffer->info; 1738 1739 unsigned int start = 0; 1740 unsigned int end; 1741 for (end = start + 1; end < count; end++) 1742 if (info[start].cluster != info[end].cluster) { 1743 normalize_glyphs_cluster (buffer, start, end, backward); 1744 start = end; 1745 } 1746 normalize_glyphs_cluster (buffer, start, end, backward); 1747 } 1748 1749 void 1750 hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)) 1751 { 1752 assert (!have_positions); 1753 for (unsigned int i = start + 1; i < end; i++) 1754 { 1755 unsigned int j = i; 1756 while (j > start && compar (&info[j - 1], &info[i]) > 0) 1757 j--; 1758 if (i == j) 1759 continue; 1760 /* Move item i to occupy place for item j, shift what's in between. */ 1761 merge_clusters (j, i + 1); 1762 { 1763 hb_glyph_info_t t = info[i]; 1764 memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t)); 1765 info[j] = t; 1766 } 1767 } 1768 } 1769 1770 /* 1771 * Debugging. 1772 */ 1773 1774 /** 1775 * hb_buffer_set_message_func: 1776 * @buffer: an #hb_buffer_t. 1777 * @func: (closure user_data) (destroy destroy) (scope notified): 1778 * @user_data: 1779 * @destroy: 1780 * 1781 * 1782 * 1783 * Since: 1.1.3 1784 **/ 1785 void 1786 hb_buffer_set_message_func (hb_buffer_t *buffer, 1787 hb_buffer_message_func_t func, 1788 void *user_data, hb_destroy_func_t destroy) 1789 { 1790 if (buffer->message_destroy) 1791 buffer->message_destroy (buffer->message_data); 1792 1793 if (func) { 1794 buffer->message_func = func; 1795 buffer->message_data = user_data; 1796 buffer->message_destroy = destroy; 1797 } else { 1798 buffer->message_func = NULL; 1799 buffer->message_data = NULL; 1800 buffer->message_destroy = NULL; 1801 } 1802 } 1803 1804 bool 1805 hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) 1806 { 1807 char buf[100]; 1808 vsnprintf (buf, sizeof (buf), fmt, ap); 1809 return (bool) this->message_func (this, font, buf, this->message_data); 1810 } 1811