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