[HarfBuzz] harfbuzz: Branch 'master' - 3 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Sat Aug 12 02:06:33 UTC 2017


 src/hb-buffer-private.hh    |   46 ++++++++++++++++++++++++
 src/hb-buffer.cc            |   83 +++++++++++++++++++++++++++++++-------------
 src/hb-buffer.h             |    6 +++
 src/hb-ot-layout-private.hh |    3 -
 src/hb-ot-shape.cc          |   27 ++++++++++++++
 5 files changed, 140 insertions(+), 25 deletions(-)

New commits:
commit 1c17c2bde5bdf74a652b78d71b64e3aaa75ec43d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 11 19:06:07 2017 -0700

    [unsafe-to-break] Copy flag to all glyphs in a cluster
    
    Makes consumption easier.

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 01972af6..25da2225 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -57,6 +57,8 @@ enum hb_buffer_scratch_flags_t {
   HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
   HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
   HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK		= 0x00000010u,
+
   /* Reserved for complex shapers' internal use. */
   HB_BUFFER_SCRATCH_FLAG_COMPLEX0			= 0x01000000u,
   HB_BUFFER_SCRATCH_FLAG_COMPLEX1			= 0x02000000u,
@@ -301,9 +303,53 @@ struct hb_buffer_t {
     }
     info.cluster = cluster;
   }
+
+  int
+  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info,
+				     unsigned int start, unsigned int end,
+				     unsigned int cluster) const
+  {
+    for (unsigned int i = start; i < end; i++)
+      cluster = MIN (cluster, info[i].cluster);
+    return cluster;
+  }
+  void
+  _unsafe_to_break_set_mask (hb_glyph_info_t *info,
+			     unsigned int start, unsigned int end,
+			     unsigned int cluster)
+  {
+    for (unsigned int i = start; i < end; i++)
+      if (cluster != info[i].cluster)
+      {
+	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
+	info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      }
+  }
 };
 
 
+/* Loop over clusters. Duplicated in foreach_syllable(). */
+#define foreach_cluster(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _next_cluster (buffer, start))
+
+static inline unsigned int
+_next_cluster (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int cluster = info[start].cluster;
+  while (++start < count && cluster == info[start].cluster)
+    ;
+
+  return start;
+}
+
+
 #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
   b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
 	   sizeof (b->info[0].var))
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index dc932692..0b3f8135 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -643,28 +643,12 @@ done:
   skip_glyph ();
 }
 
-static int
-unsafe_to_break_find_min (const hb_glyph_info_t *info, unsigned int start, unsigned int end,
-			  unsigned int cluster)
-{
-  for (unsigned int i = start; i < end; i++)
-    cluster = MIN (cluster, info[i].cluster);
-  return cluster;
-}
-static void
-unsafe_to_break_set_mask (hb_glyph_info_t *info, unsigned int start, unsigned int end,
-			  unsigned int cluster)
-{
-  for (unsigned int i = start; i < end; i++)
-    if (cluster != info[i].cluster)
-      info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-}
 void
 hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
 {
   unsigned int cluster = (unsigned int) -1;
-  cluster = unsafe_to_break_find_min (info, start, end, cluster);
-  unsafe_to_break_set_mask (info, start, end, cluster);
+  cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
+  _unsafe_to_break_set_mask (info, start, end, cluster);
 }
 void
 hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
@@ -679,10 +663,10 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
   assert (idx <= end);
 
   unsigned int cluster = (unsigned int) -1;
-  cluster = unsafe_to_break_find_min (out_info, start, out_len, cluster);
-  cluster = unsafe_to_break_find_min (info, idx, end, cluster);
-  unsafe_to_break_set_mask (out_info, start, out_len, cluster);
-  unsafe_to_break_set_mask (info, idx, end, cluster);
+  cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
+  cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
+  _unsafe_to_break_set_mask (out_info, start, out_len, cluster);
+  _unsafe_to_break_set_mask (info, idx, end, cluster);
 }
 
 void
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index b476339e..d4ac60b0 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -197,8 +197,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
 #define syllable()		var1.u8[3] /* GSUB/GPOS shaping boundaries */
 
 
-/* loop over syllables */
-
+/* Loop over syllables. Based on foreach_cluster(). */
 #define foreach_syllable(buffer, start, end) \
   for (unsigned int \
        _count = buffer->len, \
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 5cd69927..bc536696 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -783,6 +783,31 @@ hb_ot_position (hb_ot_shape_context_t *c)
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
 }
 
+static inline void
+hb_propagate_flags (hb_buffer_t *buffer)
+{
+  /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
+   * Simplifies using them. */
+
+  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
+    return;
+
+  hb_glyph_info_t *info = buffer->info;
+
+  foreach_cluster (buffer, start, end)
+  {
+    unsigned int mask = 0;
+    for (unsigned int i = start; i < end; i++)
+      if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+      {
+	 mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+	 break;
+      }
+    if (mask)
+      for (unsigned int i = start; i < end; i++)
+	info[i].mask |= mask;
+  }
+}
 
 /* Pull it all together! */
 
@@ -826,6 +851,8 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
   if (c->plan->shaper->postprocess_glyphs)
     c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
 
+  hb_propagate_flags (c->buffer);
+
   _hb_buffer_deallocate_unicode_vars (c->buffer);
 
   c->buffer->props.direction = c->target_direction;
commit ec104e5912417c0fdc8c7cb004c684aea26eb1dc
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 11 18:24:27 2017 -0700

    [unsafe-to-break] Mark unsafe is cluster merging is disabled
    
    We were relying on cluster merges not requiring unsafe flagging because
    they get merged.  If cluster level requests no merging, then we flag
    unsafe when merge would have happened.

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 89576f01..dc932692 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -550,7 +550,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
 				  unsigned int end)
 {
   if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+  {
+    unsafe_to_break (start, end);
     return;
+  }
 
   unsigned int cluster = info[start].cluster;
 
commit 39a97494304a7e6b8999e59a92ce4d24ba9b881a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 11 15:52:06 2017 -0700

    New API: hb_buffer_append()

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 4b0f9603..89576f01 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1711,6 +1711,55 @@ hb_buffer_add_codepoints (hb_buffer_t          *buffer,
 }
 
 
+/**
+ * hb_buffer_append:
+ * @buffer: an #hb_buffer_t.
+ * @source: source #hb_buffer_t.
+ * @start: start index into source buffer to copy.  Use 0 to copy from start of buffer.
+ * @end: end index into source buffer to copy.  Use (unsigned int) -1 to copy to end of buffer.
+ *
+ * Append (part of) contents of another buffer to this buffer.
+ *
+ * Since: 1.5.0
+ **/
+HB_EXTERN void
+hb_buffer_append (hb_buffer_t *buffer,
+		  hb_buffer_t *source,
+		  unsigned int start,
+		  unsigned int end)
+{
+  assert (!buffer->have_output && !source->have_output);
+  assert (buffer->have_positions == source->have_positions);
+  assert (buffer->content_type == source->content_type ||
+	  !buffer->len || !source->len);
+
+  if (end > source->len)
+    end = source->len;
+  if (start > end)
+    start = end;
+  if (start == end)
+    return;
+
+  if (!buffer->len)
+    buffer->content_type = source->content_type;
+
+  if (buffer->len + (end - start) > buffer->len) /* Overflows. */
+  {
+    buffer->in_error = true;
+    return;
+  }
+
+  unsigned int orig_len = buffer->len;
+  hb_buffer_set_length (buffer, buffer->len + (end - start));
+  if (buffer->in_error)
+    return;
+
+  memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
+  if (buffer->have_positions)
+    memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
+}
+
+
 static int
 compare_info_codepoint (const hb_glyph_info_t *pa,
 			const hb_glyph_info_t *pb)
@@ -1781,7 +1830,8 @@ void
 hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
 {
   assert (buffer->have_positions);
-  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
+  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS ||
+	  (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
   bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
 
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 0869fafe..1d40747f 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -169,6 +169,7 @@ HB_EXTERN void *
 hb_buffer_get_user_data (hb_buffer_t        *buffer,
 			 hb_user_data_key_t *key);
 
+
 /**
  * hb_buffer_content_type_t:
  * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
@@ -365,6 +366,11 @@ hb_buffer_add_codepoints (hb_buffer_t          *buffer,
 			  unsigned int          item_offset,
 			  int                   item_length);
 
+HB_EXTERN void
+hb_buffer_append (hb_buffer_t *buffer,
+		  hb_buffer_t *source,
+		  unsigned int start,
+		  unsigned int end);
 
 HB_EXTERN hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,


More information about the HarfBuzz mailing list