[buffer] In hb_buffer_get_positions(), return NULL if inside message callback

As discussed in https://github.com/harfbuzz/harfbuzz/issues/2468#issuecomment-645666066

Part of fixing https://github.com/harfbuzz/harfbuzz/issues/2468
This commit is contained in:
Behdad Esfahbod 2021-06-10 17:33:29 -06:00
parent 855a3f478e
commit c61ce962cf
3 changed files with 23 additions and 4 deletions

View File

@ -1363,6 +1363,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
* Returns @buffer glyph position array. Returned pointer * Returns @buffer glyph position array. Returned pointer
* is valid as long as @buffer contents are not modified. * is valid as long as @buffer contents are not modified.
* *
* If buffer did not have positions before, the positions will be
* initialized to zeros, unless this function is called from
* within a buffer message callback (see hb_buffer_set_message_func()),
* in which case %NULL is returned.
*
* Return value: (transfer none) (array length=length): * Return value: (transfer none) (array length=length):
* The @buffer glyph position array. * The @buffer glyph position array.
* The value valid as long as buffer has not been modified. * The value valid as long as buffer has not been modified.
@ -1373,12 +1378,17 @@ hb_glyph_position_t *
hb_buffer_get_glyph_positions (hb_buffer_t *buffer, hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
unsigned int *length) unsigned int *length)
{ {
if (!buffer->have_positions)
buffer->clear_positions ();
if (length) if (length)
*length = buffer->len; *length = buffer->len;
if (!buffer->have_positions)
{
if (unlikely (buffer->message_depth))
return nullptr;
buffer->clear_positions ();
}
return (hb_glyph_position_t *) buffer->pos; return (hb_glyph_position_t *) buffer->pos;
} }

View File

@ -128,6 +128,9 @@ struct hb_buffer_t
hb_buffer_message_func_t message_func; hb_buffer_message_func_t message_func;
void *message_data; void *message_data;
hb_destroy_func_t message_destroy; hb_destroy_func_t message_destroy;
unsigned message_depth; /* How deeply are we inside a message callback? */
#else
static constexpr unsigned message_depth = 0u;
#endif #endif
/* Internal debugging. */ /* Internal debugging. */
@ -400,10 +403,16 @@ struct hb_buffer_t
#else #else
if (!messaging ()) if (!messaging ())
return true; return true;
message_depth++;
va_list ap; va_list ap;
va_start (ap, fmt); va_start (ap, fmt);
bool ret = message_impl (font, fmt, ap); bool ret = message_impl (font, fmt, ap);
va_end (ap); va_end (ap);
message_depth--;
return ret; return ret;
#endif #endif
} }

View File

@ -454,7 +454,7 @@ shape_options_t::add_options (option_parser_t *parser)
{"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},
{"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', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, {"num-iterations", 'n', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
{nullptr} {nullptr}
}; };
parser->add_group (entries, parser->add_group (entries,