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