[buffer] Add HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT

Fixes https://github.com/harfbuzz/harfbuzz/issues/3454
This commit is contained in:
Behdad Esfahbod 2022-02-18 14:08:43 -06:00
parent c0b2f50c0b
commit 56f11ec938
5 changed files with 21 additions and 5 deletions

View File

@ -397,7 +397,8 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
ret = false; ret = false;
if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers)) if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers))
ret = false; ret = false;
if (!buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers)) if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 &&
!buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
ret = false; ret = false;
if (!ret) if (!ret)
{ {

View File

@ -137,7 +137,11 @@ typedef struct hb_glyph_info_t {
* clusters. * clusters.
* The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
* always imply this flag. * always imply this flag.
* Since: 3.3.0 * To use this flag, you must enable the buffer flag
* @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during
* shaping, otherwise the buffer flag will not be
* reliably produced.
* Since: REPLACEME
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
* *
* Flags for #hb_glyph_info_t. * Flags for #hb_glyph_info_t.
@ -365,7 +369,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* handler is installed on the buffer, or a message is written * handler is installed on the buffer, or a message is written
* to standard error. In either case, the shaping result might * to standard error. In either case, the shaping result might
* be modified to show the failed output. Since: 3.4.0 * be modified to show the failed output. Since: 3.4.0
* * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT:
* flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
* glyph-flag should be produced by the shaper. By default
* it will not be produced since it incurs a cost. Since: REPLACEME
* Flags for #hb_buffer_t. * Flags for #hb_buffer_t.
* *
* Since: 0.9.20 * Since: 0.9.20
@ -377,7 +384,8 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u, HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u, HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u, HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
HB_BUFFER_FLAG_VERIFY = 0x00000020u HB_BUFFER_FLAG_VERIFY = 0x00000020u,
HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
} hb_buffer_flags_t; } hb_buffer_flags_t;
HB_EXTERN void HB_EXTERN void

View File

@ -460,6 +460,8 @@ struct hb_buffer_t
} }
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{ {
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end, start, end,
true); true);
@ -472,6 +474,8 @@ struct hb_buffer_t
} }
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{ {
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end, start, end,
false, true); false, true);

View File

@ -1 +1 @@
../fonts/34da9aab7bee86c4dfc3b85e423435822fdf4b62.ttf;--show-flags;U+0628,U+200C,U+0628;[uni0628=1+993#2|uni0628=0+993#2] ../fonts/34da9aab7bee86c4dfc3b85e423435822fdf4b62.ttf;--show-flags --unsafe-to-concat;U+0628,U+200C,U+0628;[uni0628=1+993#2|uni0628=0+993#2]

View File

@ -52,6 +52,7 @@ struct shape_options_t
(bot ? HB_BUFFER_FLAG_BOT : 0) | (bot ? HB_BUFFER_FLAG_BOT : 0) |
(eot ? HB_BUFFER_FLAG_EOT : 0) | (eot ? HB_BUFFER_FLAG_EOT : 0) |
(verify ? HB_BUFFER_FLAG_VERIFY : 0) | (verify ? HB_BUFFER_FLAG_VERIFY : 0) |
(unsafe_to_concat ? HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT : 0) |
(preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) | (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) |
(remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) | (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) |
0)); 0));
@ -137,6 +138,7 @@ struct shape_options_t
hb_buffer_cluster_level_t cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; hb_buffer_cluster_level_t cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
hb_bool_t normalize_glyphs = false; hb_bool_t normalize_glyphs = false;
hb_bool_t verify = false; hb_bool_t verify = false;
hb_bool_t unsafe_to_concat = false;
unsigned int num_iterations = 1; unsigned int num_iterations = 1;
}; };
@ -260,6 +262,7 @@ shape_options_t::add_options (option_parser_t *parser)
{"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr}, {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr},
{"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"}, {"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", nullptr}, {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr},
{"unsafe-to-concat",0, 0, G_OPTION_ARG_NONE, &this->unsafe_to_concat, "Produce unsafe-to-concat glyph flag", nullptr},
{"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr}, {"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr},
{"num-iterations", 'n', G_OPTION_FLAG_IN_MAIN, {"num-iterations", 'n', G_OPTION_FLAG_IN_MAIN,
G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},