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 <beh...@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 <beh...@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 <beh...@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 <beh...@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; _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/harfbuzz