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