Imported Upstream version 0.9.3
[platform/upstream/harfbuzz.git] / src / hb-buffer.cc
1 /*
2  * Copyright © 1998-2004  David Turner and Werner Lemberg
3  * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
4  * Copyright © 2011  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
32 #include <string.h>
33
34
35
36 #ifndef HB_DEBUG_BUFFER
37 #define HB_DEBUG_BUFFER (HB_DEBUG+0)
38 #endif
39
40 /* Here is how the buffer works internally:
41  *
42  * There are two info pointers: info and out_info.  They always have
43  * the same allocated size, but different lengths.
44  *
45  * As an optimization, both info and out_info may point to the
46  * same piece of memory, which is owned by info.  This remains the
47  * case as long as out_len doesn't exceed i at any time.
48  * In that case, swap_buffers() is no-op and the glyph operations operate
49  * mostly in-place.
50  *
51  * As soon as out_info gets longer than info, out_info is moved over
52  * to an alternate buffer (which we reuse the pos buffer for!), and its
53  * current contents (out_len entries) are copied to the new place.
54  * This should all remain transparent to the user.  swap_buffers() then
55  * switches info and out_info.
56  */
57
58
59
60 /* Internal API */
61
62 bool
63 hb_buffer_t::enlarge (unsigned int size)
64 {
65   if (unlikely (in_error))
66     return false;
67
68   unsigned int new_allocated = allocated;
69   hb_glyph_position_t *new_pos = NULL;
70   hb_glyph_info_t *new_info = NULL;
71   bool separate_out = out_info != info;
72
73   if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
74     goto done;
75
76   while (size > new_allocated)
77     new_allocated += (new_allocated >> 1) + 32;
78
79   ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
80   if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
81     goto done;
82
83   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
84   new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
85
86 done:
87   if (unlikely (!new_pos || !new_info))
88     in_error = true;
89
90   if (likely (new_pos))
91     pos = new_pos;
92
93   if (likely (new_info))
94     info = new_info;
95
96   out_info = separate_out ? (hb_glyph_info_t *) pos : info;
97   if (likely (!in_error))
98     allocated = new_allocated;
99
100   return likely (!in_error);
101 }
102
103 bool
104 hb_buffer_t::make_room_for (unsigned int num_in,
105                             unsigned int num_out)
106 {
107   if (unlikely (!ensure (out_len + num_out))) return false;
108
109   if (out_info == info &&
110       out_len + num_out > idx + num_in)
111   {
112     assert (have_output);
113
114     out_info = (hb_glyph_info_t *) pos;
115     memcpy (out_info, info, out_len * sizeof (out_info[0]));
116   }
117
118   return true;
119 }
120
121 void *
122 hb_buffer_t::get_scratch_buffer (unsigned int *size)
123 {
124   have_output = false;
125   have_positions = false;
126
127   out_len = 0;
128   out_info = info;
129
130   *size = allocated * sizeof (pos[0]);
131   return pos;
132 }
133
134
135
136 /* HarfBuzz-Internal API */
137
138 void
139 hb_buffer_t::reset (void)
140 {
141   if (unlikely (hb_object_is_inert (this)))
142     return;
143
144   hb_unicode_funcs_destroy (unicode);
145   unicode = hb_unicode_funcs_get_default ();
146
147   hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT;
148   props = default_props;
149
150   in_error = false;
151   have_output = false;
152   have_positions = false;
153
154   idx = 0;
155   len = 0;
156   out_len = 0;
157   out_info = info;
158
159   serial = 0;
160   memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
161   memset (allocated_var_owner, 0, sizeof allocated_var_owner);
162 }
163
164 void
165 hb_buffer_t::add (hb_codepoint_t  codepoint,
166                   hb_mask_t       mask,
167                   unsigned int    cluster)
168 {
169   hb_glyph_info_t *glyph;
170
171   if (unlikely (!ensure (len + 1))) return;
172
173   glyph = &info[len];
174
175   memset (glyph, 0, sizeof (*glyph));
176   glyph->codepoint = codepoint;
177   glyph->mask = mask;
178   glyph->cluster = cluster;
179
180   len++;
181 }
182
183 void
184 hb_buffer_t::clear_output (void)
185 {
186   if (unlikely (hb_object_is_inert (this)))
187     return;
188
189   have_output = true;
190   have_positions = false;
191
192   out_len = 0;
193   out_info = info;
194 }
195
196 void
197 hb_buffer_t::clear_positions (void)
198 {
199   if (unlikely (hb_object_is_inert (this)))
200     return;
201
202   have_output = false;
203   have_positions = true;
204
205   out_len = 0;
206   out_info = info;
207
208   memset (pos, 0, sizeof (pos[0]) * len);
209 }
210
211 void
212 hb_buffer_t::swap_buffers (void)
213 {
214   if (unlikely (in_error)) return;
215
216   assert (have_output);
217   have_output = false;
218
219   if (out_info != info)
220   {
221     hb_glyph_info_t *tmp_string;
222     tmp_string = info;
223     info = out_info;
224     out_info = tmp_string;
225     pos = (hb_glyph_position_t *) out_info;
226   }
227
228   unsigned int tmp;
229   tmp = len;
230   len = out_len;
231   out_len = tmp;
232
233   idx = 0;
234 }
235
236
237 void
238 hb_buffer_t::replace_glyphs (unsigned int num_in,
239                              unsigned int num_out,
240                              const uint32_t *glyph_data)
241 {
242   if (unlikely (!make_room_for (num_in, num_out))) return;
243
244   merge_clusters (idx, idx + num_in);
245
246   hb_glyph_info_t orig_info = info[idx];
247   hb_glyph_info_t *pinfo = &out_info[out_len];
248   for (unsigned int i = 0; i < num_out; i++)
249   {
250     *pinfo = orig_info;
251     pinfo->codepoint = glyph_data[i];
252     pinfo++;
253   }
254
255   idx  += num_in;
256   out_len += num_out;
257 }
258
259 void
260 hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
261 {
262   if (unlikely (!make_room_for (0, 1))) return;
263
264   out_info[out_len] = info[idx];
265   out_info[out_len].codepoint = glyph_index;
266
267   out_len++;
268 }
269
270 void
271 hb_buffer_t::copy_glyph (void)
272 {
273   if (unlikely (!make_room_for (0, 1))) return;
274
275   out_info[out_len] = info[idx];
276
277   out_len++;
278 }
279
280 void
281 hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
282 {
283   if (unlikely (out_info != info || out_len != idx)) {
284     if (unlikely (!make_room_for (1, 1))) return;
285     out_info[out_len] = info[idx];
286   }
287   out_info[out_len].codepoint = glyph_index;
288
289   idx++;
290   out_len++;
291 }
292
293 void
294 hb_buffer_t::next_glyph (void)
295 {
296   if (have_output)
297   {
298     if (unlikely (out_info != info || out_len != idx)) {
299       if (unlikely (!make_room_for (1, 1))) return;
300       out_info[out_len] = info[idx];
301     }
302     out_len++;
303   }
304
305   idx++;
306 }
307
308
309 void
310 hb_buffer_t::set_masks (hb_mask_t    value,
311                         hb_mask_t    mask,
312                         unsigned int cluster_start,
313                         unsigned int cluster_end)
314 {
315   hb_mask_t not_mask = ~mask;
316   value &= mask;
317
318   if (!mask)
319     return;
320
321   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
322     unsigned int count = len;
323     for (unsigned int i = 0; i < count; i++)
324       info[i].mask = (info[i].mask & not_mask) | value;
325     return;
326   }
327
328   unsigned int count = len;
329   for (unsigned int i = 0; i < count; i++)
330     if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
331       info[i].mask = (info[i].mask & not_mask) | value;
332 }
333
334 void
335 hb_buffer_t::reverse_range (unsigned int start,
336                             unsigned int end)
337 {
338   unsigned int i, j;
339
340   if (start == end - 1)
341     return;
342
343   for (i = start, j = end - 1; i < j; i++, j--) {
344     hb_glyph_info_t t;
345
346     t = info[i];
347     info[i] = info[j];
348     info[j] = t;
349   }
350
351   if (pos) {
352     for (i = start, j = end - 1; i < j; i++, j--) {
353       hb_glyph_position_t t;
354
355       t = pos[i];
356       pos[i] = pos[j];
357       pos[j] = t;
358     }
359   }
360 }
361
362 void
363 hb_buffer_t::reverse (void)
364 {
365   if (unlikely (!len))
366     return;
367
368   reverse_range (0, len);
369 }
370
371 void
372 hb_buffer_t::reverse_clusters (void)
373 {
374   unsigned int i, start, count, last_cluster;
375
376   if (unlikely (!len))
377     return;
378
379   reverse ();
380
381   count = len;
382   start = 0;
383   last_cluster = info[0].cluster;
384   for (i = 1; i < count; i++) {
385     if (last_cluster != info[i].cluster) {
386       reverse_range (start, i);
387       start = i;
388       last_cluster = info[i].cluster;
389     }
390   }
391   reverse_range (start, i);
392 }
393
394 void
395 hb_buffer_t::merge_clusters (unsigned int start,
396                              unsigned int end)
397 {
398   if (unlikely (end - start < 2))
399     return;
400
401   unsigned int cluster = info[start].cluster;
402
403   for (unsigned int i = start + 1; i < end; i++)
404     cluster = MIN (cluster, info[i].cluster);
405
406   /* Extend end */
407   while (end < len && info[end - 1].cluster == info[end].cluster)
408     end++;
409
410   /* Extend start */
411   while (idx < start && info[start - 1].cluster == info[start].cluster)
412     start--;
413
414   /* If we hit the start of buffer, continue in out-buffer. */
415   if (idx == start)
416     for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
417       out_info[i - 1].cluster = cluster;
418
419   for (unsigned int i = start; i < end; i++)
420     info[i].cluster = cluster;
421 }
422 void
423 hb_buffer_t::merge_out_clusters (unsigned int start,
424                                  unsigned int end)
425 {
426   if (unlikely (end - start < 2))
427     return;
428
429   unsigned int cluster = out_info[start].cluster;
430
431   for (unsigned int i = start + 1; i < end; i++)
432     cluster = MIN (cluster, out_info[i].cluster);
433
434   /* Extend start */
435   while (start && out_info[start - 1].cluster == out_info[start].cluster)
436     start--;
437
438   /* Extend end */
439   while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster)
440     end++;
441
442   /* If we hit the end of out-buffer, continue in buffer. */
443   if (end == out_len)
444     for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
445       info[i].cluster = cluster;
446
447   for (unsigned int i = start; i < end; i++)
448     out_info[i].cluster = cluster;
449 }
450
451 void
452 hb_buffer_t::guess_properties (void)
453 {
454   /* If script is set to INVALID, guess from buffer contents */
455   if (props.script == HB_SCRIPT_INVALID) {
456     for (unsigned int i = 0; i < len; i++) {
457       hb_script_t script = unicode->script (info[i].codepoint);
458       if (likely (script != HB_SCRIPT_COMMON &&
459                   script != HB_SCRIPT_INHERITED &&
460                   script != HB_SCRIPT_UNKNOWN)) {
461         props.script = script;
462         break;
463       }
464     }
465   }
466
467   /* If direction is set to INVALID, guess from script */
468   if (props.direction == HB_DIRECTION_INVALID) {
469     props.direction = hb_script_get_horizontal_direction (props.script);
470   }
471
472   /* If language is not set, use default language from locale */
473   if (props.language == HB_LANGUAGE_INVALID) {
474     /* TODO get_default_for_script? using $LANGUAGE */
475     props.language = hb_language_get_default ();
476   }
477 }
478
479
480 static inline void
481 dump_var_allocation (const hb_buffer_t *buffer)
482 {
483   char buf[80];
484   for (unsigned int i = 0; i < 8; i++)
485     buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
486   buf[8] = '\0';
487   DEBUG_MSG (BUFFER, buffer,
488              "Current var allocation: %s",
489              buf);
490 }
491
492 void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
493 {
494   assert (byte_i < 8 && byte_i + count <= 8);
495
496   if (DEBUG (BUFFER))
497     dump_var_allocation (this);
498   DEBUG_MSG (BUFFER, this,
499              "Allocating var bytes %d..%d for %s",
500              byte_i, byte_i + count - 1, owner);
501
502   for (unsigned int i = byte_i; i < byte_i + count; i++) {
503     assert (!allocated_var_bytes[i]);
504     allocated_var_bytes[i]++;
505     allocated_var_owner[i] = owner;
506   }
507 }
508
509 void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
510 {
511   if (DEBUG (BUFFER))
512     dump_var_allocation (this);
513
514   DEBUG_MSG (BUFFER, this,
515              "Deallocating var bytes %d..%d for %s",
516              byte_i, byte_i + count - 1, owner);
517
518   assert (byte_i < 8 && byte_i + count <= 8);
519   for (unsigned int i = byte_i; i < byte_i + count; i++) {
520     assert (allocated_var_bytes[i]);
521     assert (0 == strcmp (allocated_var_owner[i], owner));
522     allocated_var_bytes[i]--;
523   }
524 }
525
526 void hb_buffer_t::deallocate_var_all (void)
527 {
528   memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
529   memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
530 }
531
532 /* Public API */
533
534 hb_buffer_t *
535 hb_buffer_create ()
536 {
537   hb_buffer_t *buffer;
538
539   if (!(buffer = hb_object_create<hb_buffer_t> ()))
540     return hb_buffer_get_empty ();
541
542   buffer->reset ();
543
544   return buffer;
545 }
546
547 hb_buffer_t *
548 hb_buffer_get_empty (void)
549 {
550   static const hb_buffer_t _hb_buffer_nil = {
551     HB_OBJECT_HEADER_STATIC,
552
553     const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
554     _HB_BUFFER_PROPS_DEFAULT,
555
556     true, /* in_error */
557     true, /* have_output */
558     true  /* have_positions */
559   };
560
561   return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
562 }
563
564 hb_buffer_t *
565 hb_buffer_reference (hb_buffer_t *buffer)
566 {
567   return hb_object_reference (buffer);
568 }
569
570 void
571 hb_buffer_destroy (hb_buffer_t *buffer)
572 {
573   if (!hb_object_destroy (buffer)) return;
574
575   hb_unicode_funcs_destroy (buffer->unicode);
576
577   free (buffer->info);
578   free (buffer->pos);
579
580   free (buffer);
581 }
582
583 hb_bool_t
584 hb_buffer_set_user_data (hb_buffer_t        *buffer,
585                          hb_user_data_key_t *key,
586                          void *              data,
587                          hb_destroy_func_t   destroy,
588                          hb_bool_t           replace)
589 {
590   return hb_object_set_user_data (buffer, key, data, destroy, replace);
591 }
592
593 void *
594 hb_buffer_get_user_data (hb_buffer_t        *buffer,
595                          hb_user_data_key_t *key)
596 {
597   return hb_object_get_user_data (buffer, key);
598 }
599
600
601 void
602 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
603                              hb_unicode_funcs_t *unicode)
604 {
605   if (unlikely (hb_object_is_inert (buffer)))
606     return;
607
608   if (!unicode)
609     unicode = hb_unicode_funcs_get_default ();
610
611
612   hb_unicode_funcs_reference (unicode);
613   hb_unicode_funcs_destroy (buffer->unicode);
614   buffer->unicode = unicode;
615 }
616
617 hb_unicode_funcs_t *
618 hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
619 {
620   return buffer->unicode;
621 }
622
623 void
624 hb_buffer_set_direction (hb_buffer_t    *buffer,
625                          hb_direction_t  direction)
626
627 {
628   if (unlikely (hb_object_is_inert (buffer)))
629     return;
630
631   buffer->props.direction = direction;
632 }
633
634 hb_direction_t
635 hb_buffer_get_direction (hb_buffer_t    *buffer)
636 {
637   return buffer->props.direction;
638 }
639
640 void
641 hb_buffer_set_script (hb_buffer_t *buffer,
642                       hb_script_t  script)
643 {
644   if (unlikely (hb_object_is_inert (buffer)))
645     return;
646
647   buffer->props.script = script;
648 }
649
650 hb_script_t
651 hb_buffer_get_script (hb_buffer_t *buffer)
652 {
653   return buffer->props.script;
654 }
655
656 void
657 hb_buffer_set_language (hb_buffer_t   *buffer,
658                         hb_language_t  language)
659 {
660   if (unlikely (hb_object_is_inert (buffer)))
661     return;
662
663   buffer->props.language = language;
664 }
665
666 hb_language_t
667 hb_buffer_get_language (hb_buffer_t *buffer)
668 {
669   return buffer->props.language;
670 }
671
672
673 void
674 hb_buffer_reset (hb_buffer_t *buffer)
675 {
676   buffer->reset ();
677 }
678
679 hb_bool_t
680 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
681 {
682   return buffer->ensure (size);
683 }
684
685 hb_bool_t
686 hb_buffer_allocation_successful (hb_buffer_t  *buffer)
687 {
688   return !buffer->in_error;
689 }
690
691 void
692 hb_buffer_add (hb_buffer_t    *buffer,
693                hb_codepoint_t  codepoint,
694                hb_mask_t       mask,
695                unsigned int    cluster)
696 {
697   buffer->add (codepoint, mask, cluster);
698 }
699
700 hb_bool_t
701 hb_buffer_set_length (hb_buffer_t  *buffer,
702                       unsigned int  length)
703 {
704   if (unlikely (hb_object_is_inert (buffer)))
705     return length == 0;
706
707   if (!buffer->ensure (length))
708     return false;
709
710   /* Wipe the new space */
711   if (length > buffer->len) {
712     memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
713     if (buffer->have_positions)
714       memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
715   }
716
717   buffer->len = length;
718   return true;
719 }
720
721 unsigned int
722 hb_buffer_get_length (hb_buffer_t *buffer)
723 {
724   return buffer->len;
725 }
726
727 /* Return value valid as long as buffer not modified */
728 hb_glyph_info_t *
729 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
730                            unsigned int *length)
731 {
732   if (length)
733     *length = buffer->len;
734
735   return (hb_glyph_info_t *) buffer->info;
736 }
737
738 /* Return value valid as long as buffer not modified */
739 hb_glyph_position_t *
740 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
741                                unsigned int *length)
742 {
743   if (!buffer->have_positions)
744     buffer->clear_positions ();
745
746   if (length)
747     *length = buffer->len;
748
749   return (hb_glyph_position_t *) buffer->pos;
750 }
751
752 void
753 hb_buffer_reverse (hb_buffer_t *buffer)
754 {
755   buffer->reverse ();
756 }
757
758 void
759 hb_buffer_reverse_clusters (hb_buffer_t *buffer)
760 {
761   buffer->reverse_clusters ();
762 }
763
764 void
765 hb_buffer_guess_properties (hb_buffer_t *buffer)
766 {
767   buffer->guess_properties ();
768 }
769
770 #define ADD_UTF(T) \
771         HB_STMT_START { \
772           if (text_length == -1) { \
773             text_length = 0; \
774             const T *p = (const T *) text; \
775             while (*p) { \
776               text_length++; \
777               p++; \
778             } \
779           } \
780           if (item_length == -1) \
781             item_length = text_length - item_offset; \
782           buffer->ensure (buffer->len + item_length * sizeof (T) / 4); \
783           const T *next = (const T *) text + item_offset; \
784           const T *end = next + item_length; \
785           while (next < end) { \
786             hb_codepoint_t u; \
787             const T *old_next = next; \
788             next = UTF_NEXT (next, end, u); \
789             hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
790           } \
791         } HB_STMT_END
792
793
794 #define UTF8_COMPUTE(Char, Mask, Len) \
795   if (Char < 128) { Len = 1; Mask = 0x7f; } \
796   else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
797   else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
798   else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
799   else Len = 0;
800
801 static inline const uint8_t *
802 hb_utf8_next (const uint8_t *text,
803               const uint8_t *end,
804               hb_codepoint_t *unicode)
805 {
806   uint8_t c = *text;
807   unsigned int mask, len;
808
809   /* TODO check for overlong sequences? */
810
811   UTF8_COMPUTE (c, mask, len);
812   if (unlikely (!len || (unsigned int) (end - text) < len)) {
813     *unicode = -1;
814     return text + 1;
815   } else {
816     hb_codepoint_t result;
817     unsigned int i;
818     result = c & mask;
819     for (i = 1; i < len; i++)
820       {
821         if (unlikely ((text[i] & 0xc0) != 0x80))
822           {
823             *unicode = -1;
824             return text + 1;
825           }
826         result <<= 6;
827         result |= (text[i] & 0x3f);
828       }
829     *unicode = result;
830     return text + len;
831   }
832 }
833
834 void
835 hb_buffer_add_utf8 (hb_buffer_t  *buffer,
836                     const char   *text,
837                     int           text_length,
838                     unsigned int  item_offset,
839                     int           item_length)
840 {
841 #define UTF_NEXT(S, E, U)       hb_utf8_next (S, E, &(U))
842   ADD_UTF (uint8_t);
843 #undef UTF_NEXT
844 }
845
846 static inline const uint16_t *
847 hb_utf16_next (const uint16_t *text,
848                const uint16_t *end,
849                hb_codepoint_t *unicode)
850 {
851   uint16_t c = *text++;
852
853   if (unlikely (c >= 0xd800 && c < 0xdc00)) {
854     /* high surrogate */
855     uint16_t l;
856     if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
857       /* low surrogate */
858       *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
859        text++;
860     } else
861       *unicode = -1;
862   } else
863     *unicode = c;
864
865   return text;
866 }
867
868 void
869 hb_buffer_add_utf16 (hb_buffer_t    *buffer,
870                      const uint16_t *text,
871                      int             text_length,
872                      unsigned int    item_offset,
873                      int            item_length)
874 {
875 #define UTF_NEXT(S, E, U)       hb_utf16_next (S, E, &(U))
876   ADD_UTF (uint16_t);
877 #undef UTF_NEXT
878 }
879
880 void
881 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
882                      const uint32_t *text,
883                      int             text_length,
884                      unsigned int    item_offset,
885                      int             item_length)
886 {
887 #define UTF_NEXT(S, E, U)       ((U) = *(S), (S)+1)
888   ADD_UTF (uint32_t);
889 #undef UTF_NEXT
890 }
891
892
893 static int
894 compare_info_codepoint (const hb_glyph_info_t *pa,
895                         const hb_glyph_info_t *pb)
896 {
897   return (int) pb->codepoint - (int) pa->codepoint;
898 }
899
900 static inline void
901 normalize_glyphs_cluster (hb_buffer_t *buffer,
902                           unsigned int start,
903                           unsigned int end,
904                           bool backward)
905 {
906   hb_glyph_position_t *pos = buffer->pos;
907
908   /* Total cluster advance */
909   hb_position_t total_x_advance = 0, total_y_advance = 0;
910   for (unsigned int i = start; i < end; i++)
911   {
912     total_x_advance += pos[i].x_advance;
913     total_y_advance += pos[i].y_advance;
914   }
915
916   hb_position_t x_advance = 0, y_advance = 0;
917   for (unsigned int i = start; i < end; i++)
918   {
919     pos[i].x_offset += x_advance;
920     pos[i].y_offset += y_advance;
921
922     x_advance += pos[i].x_advance;
923     y_advance += pos[i].y_advance;
924
925     pos[i].x_advance = 0;
926     pos[i].y_advance = 0;
927   }
928
929   if (backward)
930   {
931     /* Transfer all cluster advance to the last glyph. */
932     pos[end - 1].x_advance = total_x_advance;
933     pos[end - 1].y_advance = total_y_advance;
934
935     hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
936   } else {
937     /* Transfer all cluster advance to the first glyph. */
938     pos[start].x_advance += total_x_advance;
939     pos[start].y_advance += total_y_advance;
940     for (unsigned int i = start + 1; i < end; i++) {
941       pos[i].x_offset -= total_x_advance;
942       pos[i].y_offset -= total_y_advance;
943     }
944     hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
945   }
946 }
947
948 void
949 hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
950 {
951   assert (buffer->have_positions);
952   /* XXX assert (buffer->have_glyphs); */
953
954   bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
955
956   unsigned int count = buffer->len;
957   if (unlikely (!count)) return;
958   hb_glyph_info_t *info = buffer->info;
959
960   unsigned int start = 0;
961   unsigned int end;
962   for (end = start + 1; end < count; end++)
963     if (info[start].cluster != info[end].cluster) {
964       normalize_glyphs_cluster (buffer, start, end, backward);
965       start = end;
966     }
967   normalize_glyphs_cluster (buffer, start, end, backward);
968 }