From 3aeee519f0b82df5263974945ae852badc4dbded Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Dec 2013 16:17:54 -0500 Subject: [PATCH] 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. --- src/hb-ot-shape.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 5390765f..1ef216c3 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -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); -- GitLab