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