Add hb_buffer_normalize_glyphs() and hb-shape --normalize-glyphs
This reorders glyphs within the cluster to a nominal order. This should have no visible effect on the output, but helps with testing, for getting the same hb-shape output for visually-equal glyphs for each cluster.
This commit is contained in:
parent
25e302da9a
commit
39b17837b4
|
@ -887,3 +887,79 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
compare_info_codepoint (const hb_glyph_info_t *pa,
|
||||
const hb_glyph_info_t *pb)
|
||||
{
|
||||
return (int) pb->codepoint - (int) pa->codepoint;
|
||||
}
|
||||
|
||||
static inline void
|
||||
normalize_glyphs_cluster (hb_buffer_t *buffer,
|
||||
unsigned int start,
|
||||
unsigned int end,
|
||||
bool backward)
|
||||
{
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
|
||||
/* Total cluster advance */
|
||||
hb_position_t total_x_advance = 0, total_y_advance = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
total_x_advance += pos[i].x_advance;
|
||||
total_y_advance += pos[i].y_advance;
|
||||
}
|
||||
|
||||
hb_position_t x_advance = 0, y_advance = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
pos[i].x_offset += x_advance;
|
||||
pos[i].y_offset += y_advance;
|
||||
|
||||
x_advance += pos[i].x_advance;
|
||||
y_advance += pos[i].y_advance;
|
||||
|
||||
pos[i].x_advance = 0;
|
||||
pos[i].y_advance = 0;
|
||||
}
|
||||
|
||||
if (backward)
|
||||
{
|
||||
/* Transfer all cluster advance to the last glyph. */
|
||||
pos[end - 1].x_advance = total_x_advance;
|
||||
pos[end - 1].y_advance = total_y_advance;
|
||||
|
||||
hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
|
||||
} else {
|
||||
/* Transfer all cluster advance to the first glyph. */
|
||||
pos[start].x_advance += total_x_advance;
|
||||
pos[start].y_advance += total_y_advance;
|
||||
for (unsigned int i = start + 1; i < end; i++) {
|
||||
pos[i].x_offset -= total_x_advance;
|
||||
pos[i].y_offset -= total_y_advance;
|
||||
}
|
||||
hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
assert (buffer->have_positions);
|
||||
/* XXX assert (buffer->have_glyphs); */
|
||||
|
||||
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
if (unlikely (!count)) return;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
unsigned int start = 0;
|
||||
unsigned int end;
|
||||
for (end = start + 1; end < count; end++)
|
||||
if (info[start].cluster != info[end].cluster) {
|
||||
normalize_glyphs_cluster (buffer, start, end, backward);
|
||||
start = end;
|
||||
}
|
||||
normalize_glyphs_cluster (buffer, start, end, backward);
|
||||
}
|
||||
|
|
|
@ -193,6 +193,19 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
|
|||
unsigned int *length);
|
||||
|
||||
|
||||
/* Reorders a glyph buffer to have canonical in-cluster glyph order / position.
|
||||
* The resulting clusters should behave identical to pre-reordering clusters.
|
||||
* NOTE: This has nothing to do with Unicode normalization. */
|
||||
void
|
||||
hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
/*
|
||||
* NOT IMPLEMENTED
|
||||
void
|
||||
hb_buffer_normalize_characters (hb_buffer_t *buffer);
|
||||
*/
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_BUFFER_H */
|
||||
|
|
|
@ -737,8 +737,8 @@ hb_in_range (T u, T lo, T hi)
|
|||
#define FLAG(x) (1<<(x))
|
||||
|
||||
|
||||
template <typename T> inline void
|
||||
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
||||
template <typename T, typename T2> inline void
|
||||
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
|
||||
{
|
||||
if (unlikely (!len))
|
||||
return;
|
||||
|
@ -748,11 +748,21 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
|||
unsigned int new_k = 0;
|
||||
|
||||
for (unsigned int j = 0; j < k; j++)
|
||||
if (compar (&array[j], &array[j+1]) > 0) {
|
||||
T t;
|
||||
t = array[j];
|
||||
array[j] = array[j + 1];
|
||||
array[j + 1] = t;
|
||||
if (compar (&array[j], &array[j+1]) > 0)
|
||||
{
|
||||
{
|
||||
T t;
|
||||
t = array[j];
|
||||
array[j] = array[j + 1];
|
||||
array[j + 1] = t;
|
||||
}
|
||||
if (array2)
|
||||
{
|
||||
T2 t;
|
||||
t = array2[j];
|
||||
array2[j] = array2[j + 1];
|
||||
array2[j + 1] = t;
|
||||
}
|
||||
|
||||
new_k = j;
|
||||
}
|
||||
|
@ -760,6 +770,11 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
|||
} while (k);
|
||||
}
|
||||
|
||||
template <typename T> inline void
|
||||
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
||||
{
|
||||
hb_bubble_sort (array, len, compar, (int *) NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -396,6 +396,7 @@ shape_options_t::add_options (option_parser_t *parser)
|
|||
{"language", 0, 0, G_OPTION_ARG_STRING, &this->language, "Set text language (default: $LANG)", "langstr"},
|
||||
{"script", 0, 0, G_OPTION_ARG_STRING, &this->script, "Set text script (default: auto)", "ISO-15924 tag"},
|
||||
{"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", NULL},
|
||||
{"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", NULL},
|
||||
{NULL}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
|
|
|
@ -148,6 +148,7 @@ struct shape_options_t : option_group_t
|
|||
num_features = 0;
|
||||
shapers = NULL;
|
||||
utf8_clusters = false;
|
||||
normalize_glyphs = false;
|
||||
|
||||
add_options (parser);
|
||||
}
|
||||
|
@ -188,7 +189,10 @@ struct shape_options_t : option_group_t
|
|||
|
||||
hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
return hb_shape_full (font, buffer, features, num_features, shapers);
|
||||
hb_bool_t res = hb_shape_full (font, buffer, features, num_features, shapers);
|
||||
if (normalize_glyphs)
|
||||
hb_buffer_normalize_glyphs (buffer);
|
||||
return res;
|
||||
}
|
||||
|
||||
void shape_closure (const char *text, int text_len,
|
||||
|
@ -208,6 +212,7 @@ struct shape_options_t : option_group_t
|
|||
unsigned int num_features;
|
||||
char **shapers;
|
||||
hb_bool_t utf8_clusters;
|
||||
hb_bool_t normalize_glyphs;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue