[test/buffer] Add more extensive UTF-8 test data from glib
[framework/uifw/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 HB_BEGIN_DECLS
35
36
37 static hb_buffer_t _hb_buffer_nil = {
38   HB_OBJECT_HEADER_STATIC,
39
40   &_hb_unicode_funcs_default,
41   {
42     HB_DIRECTION_INVALID,
43     HB_SCRIPT_INVALID,
44     NULL,
45   },
46
47   TRUE, /* in_error */
48   TRUE, /* have_output */
49   TRUE  /* have_positions */
50 };
51
52 /* Here is how the buffer works internally:
53  *
54  * There are two info pointers: info and out_info.  They always have
55  * the same allocated size, but different lengths.
56  *
57  * As an optimization, both info and out_info may point to the
58  * same piece of memory, which is owned by info.  This remains the
59  * case as long as out_len doesn't exceed i at any time.
60  * In that case, swap() is no-op and the glyph operations operate
61  * mostly in-place.
62  *
63  * As soon as out_info gets longer than info, out_info is moved over
64  * to an alternate buffer (which we reuse the pos buffer for!), and its
65  * current contents (out_len entries) are copied to the new place.
66  * This should all remain transparent to the user.  swap() then
67  * switches info and out_info.
68  */
69
70
71 static hb_bool_t
72 _hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
73 {
74   if (unlikely (buffer->in_error))
75     return FALSE;
76
77   unsigned int new_allocated = buffer->allocated;
78   hb_glyph_position_t *new_pos = NULL;
79   hb_glyph_info_t *new_info = NULL;
80   bool separate_out = buffer->out_info != buffer->info;
81
82   if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (buffer->info[0]))))
83     goto done;
84
85   while (size > new_allocated)
86     new_allocated += (new_allocated >> 1) + 32;
87
88   ASSERT_STATIC (sizeof (buffer->info[0]) == sizeof (buffer->pos[0]));
89   if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (buffer->info[0]))))
90     goto done;
91
92   new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
93   new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
94
95 done:
96   if (unlikely (!new_pos || !new_info))
97     buffer->in_error = TRUE;
98
99   if (likely (new_pos))
100     buffer->pos = new_pos;
101
102   if (likely (new_info))
103     buffer->info = new_info;
104
105   buffer->out_info = separate_out ? (hb_glyph_info_t *) buffer->pos : buffer->info;
106   if (likely (!buffer->in_error))
107     buffer->allocated = new_allocated;
108
109   return likely (!buffer->in_error);
110 }
111
112 static inline hb_bool_t
113 _hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
114 {
115   return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size);
116 }
117
118 static inline hb_bool_t
119 _hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
120 {
121   if (unlikely (!size || !_hb_buffer_ensure (buffer, size))) return FALSE;
122
123   if (buffer->out_info == buffer->info)
124   {
125     assert (buffer->have_output);
126
127     buffer->out_info = (hb_glyph_info_t *) buffer->pos;
128     memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->out_info[0]));
129   }
130
131   return TRUE;
132 }
133
134
135 /* Public API */
136
137 hb_buffer_t *
138 hb_buffer_create (unsigned int pre_alloc_size)
139 {
140   hb_buffer_t *buffer;
141
142   if (!(buffer = hb_object_create<hb_buffer_t> ()))
143     return &_hb_buffer_nil;
144
145   if (pre_alloc_size)
146     _hb_buffer_ensure (buffer, pre_alloc_size);
147
148   hb_buffer_reset (buffer);
149
150   return buffer;
151 }
152
153 hb_buffer_t *
154 hb_buffer_reference (hb_buffer_t *buffer)
155 {
156   return hb_object_reference (buffer);
157 }
158
159 void
160 hb_buffer_destroy (hb_buffer_t *buffer)
161 {
162   if (!hb_object_destroy (buffer)) return;
163
164   hb_unicode_funcs_destroy (buffer->unicode);
165
166   free (buffer->info);
167   free (buffer->pos);
168
169   free (buffer);
170 }
171
172 hb_bool_t
173 hb_buffer_set_user_data (hb_buffer_t        *buffer,
174                          hb_user_data_key_t *key,
175                          void *              data,
176                          hb_destroy_func_t   destroy)
177 {
178   return hb_object_set_user_data (buffer, key, data, destroy);
179 }
180
181 void *
182 hb_buffer_get_user_data (hb_buffer_t        *buffer,
183                          hb_user_data_key_t *key)
184 {
185   return hb_object_get_user_data (buffer, key);
186 }
187
188
189 void
190 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
191                              hb_unicode_funcs_t *unicode)
192 {
193   if (unlikely (hb_object_is_inert (buffer)))
194     return;
195
196   if (!unicode)
197     unicode = _hb_buffer_nil.unicode;
198
199   hb_unicode_funcs_reference (unicode);
200   hb_unicode_funcs_destroy (buffer->unicode);
201   buffer->unicode = unicode;
202 }
203
204 hb_unicode_funcs_t *
205 hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
206 {
207   return buffer->unicode;
208 }
209
210 void
211 hb_buffer_set_direction (hb_buffer_t    *buffer,
212                          hb_direction_t  direction)
213
214 {
215   if (unlikely (hb_object_is_inert (buffer)))
216     return;
217
218   buffer->props.direction = direction;
219 }
220
221 hb_direction_t
222 hb_buffer_get_direction (hb_buffer_t    *buffer)
223 {
224   return buffer->props.direction;
225 }
226
227 void
228 hb_buffer_set_script (hb_buffer_t *buffer,
229                       hb_script_t  script)
230 {
231   if (unlikely (hb_object_is_inert (buffer)))
232     return;
233
234   buffer->props.script = script;
235 }
236
237 hb_script_t
238 hb_buffer_get_script (hb_buffer_t *buffer)
239 {
240   return buffer->props.script;
241 }
242
243 void
244 hb_buffer_set_language (hb_buffer_t   *buffer,
245                         hb_language_t  language)
246 {
247   if (unlikely (hb_object_is_inert (buffer)))
248     return;
249
250   buffer->props.language = language;
251 }
252
253 hb_language_t
254 hb_buffer_get_language (hb_buffer_t *buffer)
255 {
256   return buffer->props.language;
257 }
258
259
260 void
261 hb_buffer_reset (hb_buffer_t *buffer)
262 {
263   if (unlikely (hb_object_is_inert (buffer)))
264     return;
265
266   hb_unicode_funcs_destroy (buffer->unicode);
267   buffer->unicode = _hb_buffer_nil.unicode;
268
269   buffer->props = _hb_buffer_nil.props;
270
271   buffer->in_error = FALSE;
272   buffer->have_output = FALSE;
273   buffer->have_positions = FALSE;
274
275   buffer->i = 0;
276   buffer->len = 0;
277   buffer->out_len = 0;
278
279   buffer->serial = 0;
280
281   buffer->out_info = buffer->info;
282 }
283
284 hb_bool_t
285 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
286 {
287   return _hb_buffer_ensure (buffer, size);
288 }
289
290 hb_bool_t
291 hb_buffer_allocation_successful (hb_buffer_t  *buffer)
292 {
293   return !buffer->in_error;
294 }
295
296 void
297 hb_buffer_add (hb_buffer_t    *buffer,
298                hb_codepoint_t  codepoint,
299                hb_mask_t       mask,
300                unsigned int    cluster)
301 {
302   hb_glyph_info_t *glyph;
303
304   if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return;
305
306   glyph = &buffer->info[buffer->len];
307
308   memset (glyph, 0, sizeof (*glyph));
309   glyph->codepoint = codepoint;
310   glyph->mask = mask;
311   glyph->cluster = cluster;
312
313   buffer->len++;
314 }
315
316 /* HarfBuzz-Internal API */
317
318 void
319 _hb_buffer_clear_output (hb_buffer_t *buffer)
320 {
321   if (unlikely (hb_object_is_inert (buffer)))
322     return;
323
324   buffer->have_output = TRUE;
325   buffer->have_positions = FALSE;
326
327   buffer->out_len = 0;
328   buffer->out_info = buffer->info;
329 }
330
331 void
332 _hb_buffer_clear_positions (hb_buffer_t *buffer)
333 {
334   if (unlikely (hb_object_is_inert (buffer)))
335     return;
336
337   buffer->have_output = FALSE;
338   buffer->have_positions = TRUE;
339
340   memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len);
341 }
342
343 void
344 _hb_buffer_swap (hb_buffer_t *buffer)
345 {
346   if (unlikely (buffer->in_error)) return;
347
348   assert (buffer->have_output);
349
350   if (buffer->out_info != buffer->info)
351   {
352     hb_glyph_info_t *tmp_string;
353     tmp_string = buffer->info;
354     buffer->info = buffer->out_info;
355     buffer->out_info = tmp_string;
356     buffer->pos = (hb_glyph_position_t *) buffer->out_info;
357   }
358
359   unsigned int tmp;
360   tmp = buffer->len;
361   buffer->len = buffer->out_len;
362   buffer->out_len = tmp;
363
364   buffer->i = 0;
365 }
366
367 void
368 _hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer,
369                                 unsigned int num_in,
370                                 unsigned int num_out,
371                                 const uint16_t *glyph_data_be)
372 {
373   if (buffer->out_info != buffer->info ||
374       buffer->out_len + num_out > buffer->i + num_in)
375   {
376     if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out)))
377       return;
378   }
379
380   hb_glyph_info_t orig_info = buffer->info[buffer->i];
381
382   for (unsigned int i = 0; i < num_out; i++)
383   {
384     hb_glyph_info_t *info = &buffer->out_info[buffer->out_len + i];
385     *info = orig_info;
386     info->codepoint = hb_be_uint16 (glyph_data_be[i]);
387   }
388
389   buffer->i  += num_in;
390   buffer->out_len += num_out;
391 }
392
393 void
394 _hb_buffer_replace_glyph (hb_buffer_t *buffer,
395                           hb_codepoint_t glyph_index)
396 {
397   hb_glyph_info_t *info;
398
399   if (buffer->out_info != buffer->info)
400   {
401     if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
402     buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
403   }
404   else if (buffer->out_len != buffer->i)
405     buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
406
407   info = &buffer->out_info[buffer->out_len];
408   info->codepoint = glyph_index;
409
410   buffer->i++;
411   buffer->out_len++;
412 }
413
414 void
415 _hb_buffer_next_glyph (hb_buffer_t *buffer)
416 {
417   if (buffer->have_output)
418   {
419     if (buffer->out_info != buffer->info)
420     {
421       if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
422       buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
423     }
424     else if (buffer->out_len != buffer->i)
425       buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
426
427     buffer->out_len++;
428   }
429
430   buffer->i++;
431 }
432
433 void
434 _hb_buffer_reset_masks (hb_buffer_t *buffer,
435                         hb_mask_t    mask)
436 {
437   unsigned int count = buffer->len;
438   for (unsigned int i = 0; i < count; i++)
439     buffer->info[i].mask = mask;
440 }
441
442 void
443 _hb_buffer_add_masks (hb_buffer_t *buffer,
444                       hb_mask_t    mask)
445 {
446   unsigned int count = buffer->len;
447   for (unsigned int i = 0; i < count; i++)
448     buffer->info[i].mask |= mask;
449 }
450
451 void
452 _hb_buffer_set_masks (hb_buffer_t *buffer,
453                       hb_mask_t    value,
454                       hb_mask_t    mask,
455                       unsigned int cluster_start,
456                       unsigned int cluster_end)
457 {
458   hb_mask_t not_mask = ~mask;
459   value &= mask;
460
461   if (!mask)
462     return;
463
464   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
465     unsigned int count = buffer->len;
466     for (unsigned int i = 0; i < count; i++)
467       buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
468     return;
469   }
470
471   /* XXX can't bsearch since .cluster may not be sorted. */
472   /* Binary search to find the start position and go from there. */
473   unsigned int min = 0, max = buffer->len;
474   while (min < max)
475   {
476     unsigned int mid = min + ((max - min) / 2);
477     if (buffer->info[mid].cluster < cluster_start)
478       min = mid + 1;
479     else
480       max = mid;
481   }
482   unsigned int count = buffer->len;
483   for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++)
484     buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
485 }
486
487
488 /* Public API again */
489
490 hb_bool_t
491 hb_buffer_set_length (hb_buffer_t  *buffer,
492                       unsigned int  length)
493 {
494   if (!_hb_buffer_ensure (buffer, length))
495     return FALSE;
496
497   /* Wipe the new space */
498   if (length > buffer->len) {
499     memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
500     if (buffer->have_positions)
501       memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
502   }
503
504   buffer->len = length;
505   return TRUE;
506 }
507
508 unsigned int
509 hb_buffer_get_length (hb_buffer_t *buffer)
510 {
511   return buffer->len;
512 }
513
514 /* Return value valid as long as buffer not modified */
515 hb_glyph_info_t *
516 hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
517                            unsigned int *length)
518 {
519   if (length)
520     *length = buffer->len;
521
522   return (hb_glyph_info_t *) buffer->info;
523 }
524
525 /* Return value valid as long as buffer not modified */
526 hb_glyph_position_t *
527 hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
528                                unsigned int *length)
529 {
530   if (!buffer->have_positions)
531     _hb_buffer_clear_positions (buffer);
532
533   if (length)
534     *length = buffer->len;
535
536   return (hb_glyph_position_t *) buffer->pos;
537 }
538
539
540 static void
541 reverse_range (hb_buffer_t *buffer,
542                unsigned int start,
543                unsigned int end)
544 {
545   unsigned int i, j;
546
547   for (i = start, j = end - 1; i < j; i++, j--) {
548     hb_glyph_info_t t;
549
550     t = buffer->info[i];
551     buffer->info[i] = buffer->info[j];
552     buffer->info[j] = t;
553   }
554
555   if (buffer->pos) {
556     for (i = 0, j = end - 1; i < j; i++, j--) {
557       hb_glyph_position_t t;
558
559       t = buffer->pos[i];
560       buffer->pos[i] = buffer->pos[j];
561       buffer->pos[j] = t;
562     }
563   }
564 }
565
566 void
567 hb_buffer_reverse (hb_buffer_t *buffer)
568 {
569   if (unlikely (!buffer->len))
570     return;
571
572   reverse_range (buffer, 0, buffer->len);
573 }
574
575 void
576 hb_buffer_reverse_clusters (hb_buffer_t *buffer)
577 {
578   unsigned int i, start, count, last_cluster;
579
580   if (unlikely (!buffer->len))
581     return;
582
583   hb_buffer_reverse (buffer);
584
585   count = buffer->len;
586   start = 0;
587   last_cluster = buffer->info[0].cluster;
588   for (i = 1; i < count; i++) {
589     if (last_cluster != buffer->info[i].cluster) {
590       reverse_range (buffer, start, i);
591       start = i;
592       last_cluster = buffer->info[i].cluster;
593     }
594   }
595   reverse_range (buffer, start, i);
596 }
597
598
599 #define ADD_UTF(T) \
600         HB_STMT_START { \
601           const T *next = (const T *) text + item_offset; \
602           const T *end = next + item_length; \
603           while (next < end) { \
604             hb_codepoint_t u; \
605             const T *old_next = next; \
606             next = UTF_NEXT (next, end, u); \
607             hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
608           } \
609         } HB_STMT_END
610
611
612 #define UTF8_COMPUTE(Char, Mask, Len) \
613   if (Char < 128) { Len = 1; Mask = 0x7f; } \
614   else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
615   else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
616   else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
617   else Len = 0;
618
619 static inline const uint8_t *
620 hb_utf8_next (const uint8_t *text,
621               const uint8_t *end,
622               hb_codepoint_t *unicode)
623 {
624   uint8_t c = *text;
625   unsigned int mask, len;
626
627   /* TODO check for overlong sequences? */
628
629   UTF8_COMPUTE (c, mask, len);
630   if (unlikely (!len || (unsigned int) (end - text) < len)) {
631     *unicode = -1;
632     return text + 1;
633   } else {
634     hb_codepoint_t result;
635     unsigned int i;
636     result = c & mask;
637     for (i = 1; i < len; i++)
638       {
639         if (unlikely ((text[i] & 0xc0) != 0x80))
640           {
641             *unicode = -1;
642             return text + 1;
643           }
644         result <<= 6;
645         result |= (text[i] & 0x3f);
646       }
647     *unicode = result;
648     return text + len;
649   }
650 }
651
652 void
653 hb_buffer_add_utf8 (hb_buffer_t  *buffer,
654                     const char   *text,
655                     unsigned int  text_length HB_UNUSED,
656                     unsigned int  item_offset,
657                     unsigned int  item_length)
658 {
659 #define UTF_NEXT(S, E, U)       hb_utf8_next (S, E, &(U))
660   ADD_UTF (uint8_t);
661 #undef UTF_NEXT
662 }
663
664 static inline const uint16_t *
665 hb_utf16_next (const uint16_t *text,
666                const uint16_t *end,
667                hb_codepoint_t *unicode)
668 {
669   uint16_t c = *text++;
670
671   if (unlikely (c >= 0xd800 && c < 0xdc00)) {
672     /* high surrogate */
673     uint16_t l;
674     if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
675       /* low surrogate */
676       *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
677        text++;
678     } else
679       *unicode = -1;
680   } else
681     *unicode = c;
682
683   return text;
684 }
685
686 void
687 hb_buffer_add_utf16 (hb_buffer_t    *buffer,
688                      const uint16_t *text,
689                      unsigned int    text_length HB_UNUSED,
690                      unsigned int    item_offset,
691                      unsigned int    item_length)
692 {
693 #define UTF_NEXT(S, E, U)       hb_utf16_next (S, E, &(U))
694   ADD_UTF (uint16_t);
695 #undef UTF_NEXT
696 }
697
698 void
699 hb_buffer_add_utf32 (hb_buffer_t    *buffer,
700                      const uint32_t *text,
701                      unsigned int    text_length HB_UNUSED,
702                      unsigned int    item_offset,
703                      unsigned int    item_length)
704 {
705 #define UTF_NEXT(S, E, U)       ((U) = *(S), (S)+1)
706   ADD_UTF (uint32_t);
707 #undef UTF_NEXT
708 }
709
710
711 HB_END_DECLS