Bug 72698 - Automatically support frac / numr / dnom

When seeing U+2044 FRACTION SLASH in the text, find decimal
digits (Unicode General Category Decimal_Number) around it,
and mark the pre-slash digits with 'numr' feature, the post-slash
digits with 'dnom' feature, and the whole sequence with 'frac'
feature.

This beautifully renders fractions with major Windows fonts,
and any other font that implements those features (numr/dnom is
enough for most fonts.)

Not the fastest way to do this, but good enough for a start.
This commit is contained in:
Behdad Esfahbod 2013-12-22 16:17:54 -05:00
parent 014f369ec9
commit 3aeee519f0
1 changed files with 51 additions and 0 deletions

View File

@ -88,6 +88,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
break;
}
map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
if (planner->shaper->collect_features)
planner->shaper->collect_features (planner);
@ -305,6 +309,51 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
}
}
static inline void
hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
bool initialized = false;
hb_mask_t frac_mask = 0, numr_mask = 0, dnom_mask = 0;
/* TODO look in pre/post context text also. */
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
if (info[i].codepoint == 0x2044) /* FRACTION SLASH */
{
if (!initialized)
{
initialized = true;
frac_mask = c->plan->map.get_1_mask (HB_TAG ('f','r','a','c'));
numr_mask = c->plan->map.get_1_mask (HB_TAG ('n','u','m','r'));
dnom_mask = c->plan->map.get_1_mask (HB_TAG ('d','n','o','m'));
if (!(frac_mask | numr_mask | dnom_mask))
return;
}
unsigned int start = i, end = i + 1;
while (start &&
_hb_glyph_info_get_general_category (&info[start - 1]) ==
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
start--;
while (end < count &&
_hb_glyph_info_get_general_category (&info[end]) ==
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
end++;
buffer->set_masks (frac_mask, frac_mask, start, end);
buffer->set_masks (numr_mask, numr_mask, start, i);
buffer->set_masks (dnom_mask, dnom_mask, i + 1, end);
i = end - 1;
}
}
}
static inline void
hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
{
@ -321,6 +370,8 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
hb_ot_map_t *map = &c->plan->map;
hb_buffer_t *buffer = c->buffer;
hb_ot_shape_setup_masks_fraction (c);
if (c->plan->shaper->setup_masks)
c->plan->shaper->setup_masks (c->plan, buffer, c->font);