< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc

Print this page

        

@@ -25,24 +25,25 @@
  *
  * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
-#include "hb-utf-private.hh"
+#include "hb-buffer.hh"
+#include "hb-utf.hh"
 
 
 /**
  * SECTION: hb-buffer
- * @title: Buffers
+ * @title: hb-buffer
  * @short_description: Input and output buffers
  * @include: hb.h
  *
  * Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
+ * passed to hb_shape(), and after shaping they hold the output glyphs.
  **/
 
+
 /**
  * hb_segment_properties_equal:
  * @a: first #hb_segment_properties_t to compare.
  * @b: second #hb_segment_properties_t to compare.
  *

@@ -122,18 +123,18 @@
   unsigned int new_allocated = allocated;
   hb_glyph_position_t *new_pos = nullptr;
   hb_glyph_info_t *new_info = nullptr;
   bool separate_out = out_info != info;
 
-  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (size, sizeof (info[0]))))
     goto done;
 
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
   static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
     goto done;
 
   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
   new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
 

@@ -180,11 +181,15 @@
 
   memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
   if (idx + count > len)
   {
     /* Under memory failure we might expose this area.  At least
-     * clean it up.  Oh well... */
+     * clean it up.  Oh well...
+     *
+     * Ideally, we should at least set Default_Ignorable bits on
+     * these, as well as consistent cluster values.  But the former
+     * is layering violation... */
     memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
   }
   len += count;
   idx += count;
 

@@ -208,27 +213,28 @@
 
 
 /* HarfBuzz-Internal API */
 
 void
-hb_buffer_t::reset (void)
+hb_buffer_t::reset ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_unicode_funcs_destroy (unicode);
-  unicode = hb_unicode_funcs_get_default ();
+  unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
   flags = HB_BUFFER_FLAG_DEFAULT;
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+  invisible = 0;
 
   clear ();
 }
 
 void
-hb_buffer_t::clear (void)
+hb_buffer_t::clear ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
   props = default_props;
   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;

@@ -279,39 +285,39 @@
   len++;
 }
 
 
 void
-hb_buffer_t::remove_output (void)
+hb_buffer_t::remove_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
   have_positions = false;
 
   out_len = 0;
   out_info = info;
 }
 
 void
-hb_buffer_t::clear_output (void)
+hb_buffer_t::clear_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = true;
   have_positions = false;
 
   out_len = 0;
   out_info = info;
 }
 
 void
-hb_buffer_t::clear_positions (void)
+hb_buffer_t::clear_positions ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
   have_positions = true;
 

@@ -320,11 +326,11 @@
 
   memset (pos, 0, sizeof (pos[0]) * len);
 }
 
 void
-hb_buffer_t::swap_buffers (void)
+hb_buffer_t::swap_buffers ()
 {
   if (unlikely (!successful)) return;
 
   assert (have_output);
   have_output = false;

@@ -352,10 +358,12 @@
                              unsigned int num_out,
                              const uint32_t *glyph_data)
 {
   if (unlikely (!make_room_for (num_in, num_out))) return;
 
+  assert (idx + num_in <= len);
+
   merge_clusters (idx, idx + num_in);
 
   hb_glyph_info_t orig_info = info[idx];
   hb_glyph_info_t *pinfo = &out_info[out_len];
   for (unsigned int i = 0; i < num_out; i++)

@@ -367,41 +375,10 @@
 
   idx  += num_in;
   out_len += num_out;
 }
 
-void
-hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-  out_info[out_len].codepoint = glyph_index;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = glyph_info;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::copy_glyph (void)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-
-  out_len++;
-}
-
 bool
 hb_buffer_t::move_to (unsigned int i)
 {
   if (!have_output)
   {

@@ -427,12 +404,18 @@
   {
     /* Tricky part: rewinding... */
     unsigned int count = out_len - i;
 
     /* This will blow in our face if memory allocation fails later
-     * in this same lookup... */
-    if (unlikely (idx < count && !shift_forward (count + 32))) return false;
+     * in this same lookup...
+     *
+     * We used to shift with extra 32 items, instead of the 0 below.
+     * But that would leave empty slots in the buffer in case of allocation
+     * failures.  Setting to zero for now to avoid other problems (see
+     * comments in shift_forward().  This can cause O(N^2) behavior more
+     * severely than adding 32 empty slots can... */
+    if (unlikely (idx < count && !shift_forward (count + 0))) return false;
 
     assert (idx >= count);
 
     idx -= count;
     out_len -= count;

@@ -440,23 +423,10 @@
   }
 
   return true;
 }
 
-void
-hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1))) return;
-    out_info[out_len] = info[idx];
-  }
-  out_info[out_len].codepoint = glyph_index;
-
-  idx++;
-  out_len++;
-}
-
 
 void
 hb_buffer_t::set_masks (hb_mask_t    value,
                         hb_mask_t    mask,
                         unsigned int cluster_start,

@@ -508,20 +478,20 @@
     }
   }
 }
 
 void
-hb_buffer_t::reverse (void)
+hb_buffer_t::reverse ()
 {
   if (unlikely (!len))
     return;
 
   reverse_range (0, len);
 }
 
 void
-hb_buffer_t::reverse_clusters (void)
+hb_buffer_t::reverse_clusters ()
 {
   unsigned int i, start, count, last_cluster;
 
   if (unlikely (!len))
     return;

@@ -664,11 +634,11 @@
   _unsafe_to_break_set_mask (out_info, start, out_len, cluster);
   _unsafe_to_break_set_mask (info, idx, end, cluster);
 }
 
 void
-hb_buffer_t::guess_segment_properties (void)
+hb_buffer_t::guess_segment_properties ()
 {
   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
   /* If script is set to INVALID, guess from buffer contents */

@@ -699,10 +669,33 @@
 }
 
 
 /* Public API */
 
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+  HB_BUFFER_FLAG_DEFAULT,
+  HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+  HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+  0, /* invisible */
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+  HB_BUFFER_MAX_LEN_DEFAULT,
+  HB_BUFFER_MAX_OPS_DEFAULT,
+
+  HB_BUFFER_CONTENT_TYPE_INVALID,
+  HB_SEGMENT_PROPERTIES_DEFAULT,
+  false, /* successful */
+  true, /* have_output */
+  true  /* have_positions */
+
+  /* Zero is good enough for everything else. */
+};
+
+
 /**
  * hb_buffer_create: (Xconstructor)
  *
  * Creates a new #hb_buffer_t with all properties to defaults.
  *

@@ -714,11 +707,11 @@
  * hb_buffer_allocation_successful() returns %false.
  *
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_create (void)
+hb_buffer_create ()
 {
   hb_buffer_t *buffer;
 
   if (!(buffer = hb_object_create<hb_buffer_t> ()))
     return hb_buffer_get_empty ();

@@ -739,33 +732,13 @@
  * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_get_empty (void)
+hb_buffer_get_empty ()
 {
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    false, /* successful */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+  return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
 }
 
 /**
  * hb_buffer_reference: (skip)
  * @buffer: an #hb_buffer_t.

@@ -898,17 +871,16 @@
  **/
 void
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
                              hb_unicode_funcs_t *unicode_funcs)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (!unicode_funcs)
     unicode_funcs = hb_unicode_funcs_get_default ();
 
-
   hb_unicode_funcs_reference (unicode_funcs);
   hb_unicode_funcs_destroy (buffer->unicode);
   buffer->unicode = unicode_funcs;
 }
 

@@ -946,11 +918,11 @@
 void
 hb_buffer_set_direction (hb_buffer_t    *buffer,
                          hb_direction_t  direction)
 
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.direction = direction;
 }
 

@@ -990,11 +962,11 @@
  **/
 void
 hb_buffer_set_script (hb_buffer_t *buffer,
                       hb_script_t  script)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.script = script;
 }
 

@@ -1025,20 +997,20 @@
  * Languages are crucial for selecting which OpenType feature to apply to the
  * buffer which can result in applying language-specific behaviour. Languages
  * are orthogonal to the scripts, and though they are related, they are
  * different concepts and should not be confused with each other.
  *
- * Use hb_language_from_string() to convert from ISO 639 language codes to
+ * Use hb_language_from_string() to convert from BCP 47 language tags to
  * #hb_language_t.
  *
  * Since: 0.9.2
  **/
 void
 hb_buffer_set_language (hb_buffer_t   *buffer,
                         hb_language_t  language)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.language = language;
 }
 

@@ -1072,11 +1044,11 @@
  **/
 void
 hb_buffer_set_segment_properties (hb_buffer_t *buffer,
                                   const hb_segment_properties_t *props)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props = *props;
 }
 

@@ -1108,11 +1080,11 @@
  **/
 void
 hb_buffer_set_flags (hb_buffer_t       *buffer,
                      hb_buffer_flags_t  flags)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->flags = flags;
 }
 

@@ -1144,11 +1116,11 @@
  **/
 void
 hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
                      hb_buffer_cluster_level_t  cluster_level)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->cluster_level = cluster_level;
 }
 

@@ -1183,11 +1155,11 @@
  **/
 void
 hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
                                      hb_codepoint_t  replacement)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->replacement = replacement;
 }
 

@@ -1208,10 +1180,50 @@
   return buffer->replacement;
 }
 
 
 /**
+ * hb_buffer_set_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ * @invisible: the invisible #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces invisible characters in
+ * the shaping result.  If set to zero (default), the glyph for the
+ * U+0020 SPACE character is used.  Otherwise, this value is used
+ * verbatim.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                               hb_codepoint_t  invisible)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->invisible = invisible;
+}
+
+/**
+ * hb_buffer_get_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ *
+ * See hb_buffer_set_invisible_glyph().
+ *
+ * Return value:
+ * The @buffer invisible #hb_codepoint_t.
+ *
+ * Since: 2.0.0
+ **/
+hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer)
+{
+  return buffer->invisible;
+}
+
+
+/**
  * hb_buffer_reset:
  * @buffer: an #hb_buffer_t.
  *
  * Resets the buffer to its initial status, as if it was just newly created
  * with hb_buffer_create().

@@ -1315,11 +1327,11 @@
  **/
 hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,
                       unsigned int  length)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return length == 0;
 
   if (!buffer->ensure (length))
     return false;
 

@@ -1496,10 +1508,12 @@
  *
  * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
  * it will be set to the process's default language as returned by
  * hb_language_get_default().  This may change in the future by
  * taking buffer script into consideration when choosing a language.
+ * Note that hb_language_get_default() is NOT threadsafe the first time
+ * it is called.  See documentation for that function for details.
  *
  * Since: 0.9.7
  **/
 void
 hb_buffer_guess_segment_properties (hb_buffer_t *buffer)

@@ -1519,11 +1533,11 @@
   const hb_codepoint_t replacement = buffer->replacement;
 
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (text_length == -1)
     text_length = utf_t::strlen (text);
 

@@ -1650,11 +1664,11 @@
                      const uint32_t *text,
                      int             text_length,
                      unsigned int    item_offset,
                      int             item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
  * hb_buffer_add_latin1:
  * @buffer: an #hb_buffer_t.

@@ -1711,11 +1725,11 @@
                           const hb_codepoint_t *text,
                           int                   text_length,
                           unsigned int          item_offset,
                           int                   item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 
 /**
  * hb_buffer_append:

@@ -1884,10 +1898,14 @@
  * Comparing buffers.
  */
 
 /**
  * hb_buffer_diff:
+ * @buffer: a buffer.
+ * @reference: other buffer to compare to.
+ * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
+ * @position_fuzz: allowed absolute difference in position values.
  *
  * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
  * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned.  This should be used by most
  * callers if just comparing two buffers is needed.
  *
< prev index next >