[HarfBuzz] harfbuzz: Branch 'master' - 4 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Wed Jul 22 08:55:11 PDT 2015
NEWS | 8 +++++
src/hb-buffer-private.hh | 10 ++++++-
src/hb-buffer.cc | 51 ++++++++++++++++++++++++++++++--------
src/hb-buffer.h | 12 ++++++++
src/hb-ot-shape-complex-hangul.cc | 13 +++------
src/hb-ot-shape.cc | 39 ++++++++++++++++++++++++++---
util/options.cc | 1
util/options.hh | 3 ++
8 files changed, 114 insertions(+), 23 deletions(-)
New commits:
commit 376d587f36b4ff10342ee6ca3bacd73532ea44c8
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Jul 22 16:51:12 2015 +0100
Implement more granular cluster-merging
TODO: Documentation.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=71445
diff --git a/NEWS b/NEWS
index d985427..a5ac906 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+
+- Removed HB_NO_MERGE_CLUSTERS hack.
+- New API:
+ hb_buffer_cluster_level_t enum
+ hb_buffer_get_cluster_level()
+ hb_buffer_set_cluster_level()
+ hb-shape / hb-view --cluster-level
+
Overview of changes leading to 0.9.41
Thursday, June 18, 2015
=====================================
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 32d5a5f..3a2db48 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -50,6 +50,7 @@ struct hb_buffer_t {
/* Information about how the text in the buffer should be treated */
hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+ hb_buffer_cluster_level_t cluster_level;
hb_codepoint_t replacement; /* U+FFFD or something else. */
/* Buffer contents */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 0a11fec..03fe8e1 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -507,9 +507,8 @@ void
hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int end)
{
-#ifdef HB_NO_MERGE_CLUSTERS
- return;
-#endif
+ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ return;
unsigned int cluster = info[start].cluster;
@@ -536,9 +535,8 @@ void
hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int end)
{
-#ifdef HB_NO_MERGE_CLUSTERS
- return;
-#endif
+ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ return;
if (unlikely (end - start < 2))
return;
@@ -738,6 +736,7 @@ hb_buffer_get_empty (void)
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_CONTENT_TYPE_INVALID,
@@ -1083,6 +1082,41 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
return buffer->flags;
}
+/**
+ * hb_buffer_set_cluster_level:
+ * @buffer: a buffer.
+ * @cluster_level:
+ *
+ *
+ *
+ * Since: 0.9.42
+ **/
+void
+hb_buffer_set_cluster_level (hb_buffer_t *buffer,
+ hb_buffer_cluster_level_t cluster_level)
+{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
+ buffer->cluster_level = cluster_level;
+}
+
+/**
+ * hb_buffer_get_cluster_level:
+ * @buffer: a buffer.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 0.9.42
+ **/
+hb_buffer_cluster_level_t
+hb_buffer_get_cluster_level (hb_buffer_t *buffer)
+{
+ return buffer->cluster_level;
+}
+
/**
* hb_buffer_set_replacement_codepoint:
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 520141b..4b285bb 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -185,7 +185,19 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer);
+typedef enum {
+ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
+ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
+ HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
+ HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
+} hb_buffer_cluster_level_t;
+
+void
+hb_buffer_set_cluster_level (hb_buffer_t *buffer,
+ hb_buffer_cluster_level_t cluster_level);
+hb_buffer_cluster_level_t
+hb_buffer_get_cluster_level (hb_buffer_t *buffer);
#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc
index 6ac18b0..763dbf0 100644
--- a/src/hb-ot-shape-complex-hangul.cc
+++ b/src/hb-ot-shape-complex-hangul.cc
@@ -209,13 +209,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t tone = info[end];
memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
info[start] = tone;
+ buffer->merge_out_clusters (start, end + 1);
}
- /* Merge clusters across the (possibly reordered) syllable+tone.
- * We want to merge even in the zero-width tone mark case here,
- * so that clustering behavior isn't dependent on how the tone mark
- * is handled by the font.
- */
- buffer->merge_out_clusters (start, end + 1);
}
else
{
@@ -296,7 +291,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
}
else
end = start + 2;
- buffer->merge_out_clusters (start, end);
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ buffer->merge_out_clusters (start, end);
continue;
}
}
@@ -368,7 +364,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
info[i++].hangul_shaping_feature() = VJMO;
if (i < end)
info[i++].hangul_shaping_feature() = TJMO;
- buffer->merge_out_clusters (start, end);
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ buffer->merge_out_clusters (start, end);
continue;
}
}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 5ead0b7..d290cad 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -264,6 +264,9 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
static void
hb_form_clusters (hb_buffer_t *buffer)
{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ return;
+
/* Loop duplicated in hb_ensure_native_direction(). */
unsigned int base = 0;
unsigned int count = buffer->len;
@@ -301,10 +304,14 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
{
buffer->reverse_range (base, i);
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ buffer->merge_clusters (base, i);
base = i;
}
}
buffer->reverse_range (base, count);
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ buffer->merge_clusters (base, count);
buffer->reverse ();
diff --git a/util/options.cc b/util/options.cc
index 0f92aec..0821a17 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -291,6 +291,7 @@ shape_options_t::add_options (option_parser_t *parser)
{"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", NULL},
{"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", NULL},
{"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", NULL},
+ {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"},
{"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", NULL},
{"num-iterations", 0, 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
{NULL}
diff --git a/util/options.hh b/util/options.hh
index 8b9b10e..6eb6c04 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -180,6 +180,7 @@ struct shape_options_t : option_group_t
num_features = 0;
shapers = NULL;
utf8_clusters = false;
+ cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
normalize_glyphs = false;
num_iterations = 1;
@@ -202,6 +203,7 @@ struct shape_options_t : option_group_t
(bot ? HB_BUFFER_FLAG_BOT : 0) |
(eot ? HB_BUFFER_FLAG_EOT : 0) |
(preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0)));
+ hb_buffer_set_cluster_level (buffer, cluster_level);
hb_buffer_guess_segment_properties (buffer);
}
@@ -265,6 +267,7 @@ struct shape_options_t : option_group_t
unsigned int num_features;
char **shapers;
hb_bool_t utf8_clusters;
+ hb_buffer_cluster_level_t cluster_level;
hb_bool_t normalize_glyphs;
unsigned int num_iterations;
};
commit a60e2cfa395718cde48eb81f43adc27b4a92e117
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Jul 22 15:49:08 2015 +0100
[ot] Don't rely on cluster numbers for ensure_native_direction()
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index bbd044f..5ead0b7 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -264,6 +264,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
static void
hb_form_clusters (hb_buffer_t *buffer)
{
+ /* Loop duplicated in hb_ensure_native_direction(). */
unsigned int base = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
@@ -290,7 +291,23 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
(HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB))
{
- hb_buffer_reverse_clusters (buffer);
+ /* Same loop as hb_form_clusters().
+ * Since form_clusters() merged clusters already, we don't merge. */
+ unsigned int base = 0;
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 1; i < count; i++)
+ {
+ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
+ {
+ buffer->reverse_range (base, i);
+ base = i;
+ }
+ }
+ buffer->reverse_range (base, count);
+
+ buffer->reverse ();
+
buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
}
}
commit 701112dad9f6e690b253f1e64f4e7e549f5ae65f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Jul 22 15:42:20 2015 +0100
[ot] Simplify form_clusters()
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index ced748f..32d5a5f 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -189,7 +189,14 @@ struct hb_buffer_t {
unsigned int cluster_end);
HB_INTERNAL void merge_clusters (unsigned int start,
- unsigned int end);
+ unsigned int end)
+ {
+ if (end - start < 2)
+ return;
+ merge_clusters_impl (start, end);
+ }
+ HB_INTERNAL void merge_clusters_impl (unsigned int start,
+ unsigned int end);
HB_INTERNAL void merge_out_clusters (unsigned int start,
unsigned int end);
/* Merge clusters for deleting current glyph, and skip it. */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 4f953f0..0a11fec 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -504,16 +504,13 @@ hb_buffer_t::reverse_clusters (void)
}
void
-hb_buffer_t::merge_clusters (unsigned int start,
- unsigned int end)
+hb_buffer_t::merge_clusters_impl (unsigned int start,
+ unsigned int end)
{
#ifdef HB_NO_MERGE_CLUSTERS
return;
#endif
- if (unlikely (end - start < 2))
- return;
-
unsigned int cluster = info[start].cluster;
for (unsigned int i = start + 1; i < end; i++)
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 8d6bb3d..bbd044f 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -264,11 +264,18 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
static void
hb_form_clusters (hb_buffer_t *buffer)
{
+ unsigned int base = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
- buffer->merge_clusters (i - 1, i + 1);
+ {
+ if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
+ {
+ buffer->merge_clusters (base, i);
+ base = i;
+ }
+ }
+ buffer->merge_clusters (base, count);
}
static void
commit 7b8b63adc5e0389fc4cf2720ef7e5804ab6c29cc
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Jul 22 15:24:26 2015 +0100
[ot] Don't mirror character if font doesn't support mirrored character!
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index a531d77..8d6bb3d 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -305,7 +305,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++) {
hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
- if (likely (codepoint == info[i].codepoint))
+ if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
info[i].mask |= rtlm_mask;
else
info[i].codepoint = codepoint;
More information about the HarfBuzz
mailing list