[OT] Avoid calling get_glyph() twice
Essentially move the glyph mapping to normalization process. The effect on Devanagari is small (but observable). Should be more observable in simple text, like ASCII.
This commit is contained in:
parent
12c0875eaf
commit
b00321ea78
@ -32,6 +32,8 @@
|
||||
#include "hb-font.h"
|
||||
#include "hb-buffer.h"
|
||||
|
||||
/* buffer var allocations, used during the normalization process */
|
||||
#define glyph_index() var1.u32
|
||||
|
||||
enum hb_ot_shape_normalization_mode_t {
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
|
||||
|
@ -258,16 +258,25 @@ compose_func (hb_unicode_funcs_t *unicode,
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar)
|
||||
set_glyph (hb_glyph_info_t &info, hb_font_t *font)
|
||||
{
|
||||
hb_font_get_glyph (font, info.codepoint, 0, &info.glyph_index());
|
||||
}
|
||||
|
||||
static inline void
|
||||
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->cur().glyph_index() = glyph;
|
||||
buffer->output_glyph (unichar);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode);
|
||||
}
|
||||
|
||||
static inline void
|
||||
next_char (hb_buffer_t *buffer)
|
||||
next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->cur().glyph_index() = glyph;
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
|
||||
@ -282,31 +291,31 @@ decompose (hb_font_t *font, hb_buffer_t *buffer,
|
||||
bool shortest,
|
||||
hb_codepoint_t ab)
|
||||
{
|
||||
hb_codepoint_t a, b, glyph;
|
||||
hb_codepoint_t a, b, a_glyph, b_glyph;
|
||||
|
||||
if (!decompose_func (buffer->unicode, ab, &a, &b) ||
|
||||
(b && !font->get_glyph (b, 0, &glyph)))
|
||||
(b && !font->get_glyph (b, 0, &b_glyph)))
|
||||
return false;
|
||||
|
||||
bool has_a = font->get_glyph (a, 0, &glyph);
|
||||
bool has_a = font->get_glyph (a, 0, &a_glyph);
|
||||
if (shortest && has_a) {
|
||||
/* Output a and b */
|
||||
output_char (buffer, a);
|
||||
output_char (buffer, a, a_glyph);
|
||||
if (b)
|
||||
output_char (buffer, b);
|
||||
output_char (buffer, b, b_glyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (decompose (font, buffer, shortest, a)) {
|
||||
if (b)
|
||||
output_char (buffer, b);
|
||||
output_char (buffer, b, b_glyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (has_a) {
|
||||
output_char (buffer, a);
|
||||
output_char (buffer, a, a_glyph);
|
||||
if (b)
|
||||
output_char (buffer, b);
|
||||
output_char (buffer, b, b_glyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -319,18 +328,18 @@ decompose_compatibility (hb_font_t *font, hb_buffer_t *buffer,
|
||||
{
|
||||
unsigned int len, i;
|
||||
hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
hb_codepoint_t glyphs[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
|
||||
len = buffer->unicode->decompose_compatibility (u, decomposed);
|
||||
if (!len)
|
||||
return false;
|
||||
|
||||
hb_codepoint_t glyph;
|
||||
for (i = 0; i < len; i++)
|
||||
if (!font->get_glyph (decomposed[i], 0, &glyph))
|
||||
if (!font->get_glyph (decomposed[i], 0, &glyphs[i]))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
output_char (buffer, decomposed[i]);
|
||||
output_char (buffer, decomposed[i], glyphs[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -343,15 +352,38 @@ decompose_current_character (hb_font_t *font, hb_buffer_t *buffer,
|
||||
|
||||
/* Kind of a cute waterfall here... */
|
||||
if (shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph))
|
||||
next_char (buffer);
|
||||
next_char (buffer, glyph);
|
||||
else if (decompose (font, buffer, shortest, buffer->cur().codepoint))
|
||||
skip_char (buffer);
|
||||
else if (!shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph))
|
||||
next_char (buffer);
|
||||
next_char (buffer, glyph);
|
||||
else if (decompose_compatibility (font, buffer, buffer->cur().codepoint))
|
||||
skip_char (buffer);
|
||||
else
|
||||
next_char (buffer);
|
||||
else {
|
||||
/* A glyph-not-found case... */
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &glyph);
|
||||
next_char (buffer, glyph);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_variation_selector_cluster (hb_font_t *font, hb_buffer_t *buffer,
|
||||
unsigned int end)
|
||||
{
|
||||
for (; buffer->idx < end - 1;) {
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
|
||||
/* The next two lines are some ugly lines... But work. */
|
||||
font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index());
|
||||
buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
|
||||
} else {
|
||||
set_glyph (buffer->cur(), font);
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
}
|
||||
if (likely (buffer->idx < end)) {
|
||||
set_glyph (buffer->cur(), font);
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -361,8 +393,7 @@ decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer,
|
||||
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
|
||||
for (unsigned int i = buffer->idx; i < end; i++)
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
|
||||
while (buffer->idx < end)
|
||||
next_char (buffer);
|
||||
handle_variation_selector_cluster (font, buffer, end);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -457,7 +488,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
buffer->clear_output ();
|
||||
count = buffer->len;
|
||||
unsigned int starter = 0;
|
||||
next_char (buffer);
|
||||
buffer->next_glyph ();
|
||||
while (buffer->idx < count)
|
||||
{
|
||||
hb_codepoint_t composed, glyph;
|
||||
@ -478,19 +509,20 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
font->get_glyph (composed, 0, &glyph))
|
||||
{
|
||||
/* Composes. */
|
||||
next_char (buffer); /* Copy to out-buffer. */
|
||||
buffer->next_glyph (); /* Copy to out-buffer. */
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
buffer->merge_out_clusters (starter, buffer->out_len);
|
||||
buffer->out_len--; /* Remove the second composable. */
|
||||
buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */
|
||||
set_glyph (buffer->out_info[starter], font);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Blocked, or doesn't compose. */
|
||||
next_char (buffer);
|
||||
buffer->next_glyph ();
|
||||
|
||||
if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0)
|
||||
starter = buffer->out_len - 1;
|
||||
|
@ -308,28 +308,12 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_map_glyphs (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
|
||||
buffer->clear_output ();
|
||||
|
||||
unsigned int count = buffer->len - 1;
|
||||
for (buffer->idx = 0; buffer->idx < count;) {
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
|
||||
font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &glyph);
|
||||
buffer->replace_glyphs (2, 1, &glyph);
|
||||
} else {
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &glyph);
|
||||
buffer->replace_glyph (glyph);
|
||||
}
|
||||
}
|
||||
if (likely (buffer->idx < buffer->len)) {
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &glyph);
|
||||
buffer->replace_glyph (glyph);
|
||||
}
|
||||
buffer->swap_buffers ();
|
||||
/* Normalization process sets up glyph_index(), we just copy it. */
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].codepoint = buffer->info[i].glyph_index();
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -337,6 +321,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_mirror_chars (c);
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index);
|
||||
|
||||
_hb_ot_shape_normalize (c->font, c->buffer,
|
||||
c->plan->shaper->normalization_preference ?
|
||||
c->plan->shaper->normalization_preference (c->plan) :
|
||||
@ -344,7 +330,9 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||
|
||||
hb_ot_shape_setup_masks (c);
|
||||
|
||||
hb_ot_map_glyphs (c->font, c->buffer);
|
||||
hb_ot_map_glyphs_fast (c->buffer);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -558,6 +546,16 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan,
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void
|
||||
hb_ot_map_glyphs_dumb (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &buffer->cur().codepoint);
|
||||
}
|
||||
|
||||
void
|
||||
hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
@ -574,7 +572,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
|
||||
/* TODO: normalization? have shapers do closure()? */
|
||||
/* TODO: Deal with mirrored chars? */
|
||||
hb_ot_map_glyphs (font, buffer);
|
||||
hb_ot_map_glyphs_dumb (font, buffer);
|
||||
|
||||
/* Seed it. It's user's responsibility to have cleard glyphs
|
||||
* if that's what they desire. */
|
||||
|
Loading…
Reference in New Issue
Block a user