Makes consumption easier.
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,
}
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))
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)
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
#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, \
_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! */
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;