From e9f28a38f54b98fa59f9159ccaaa3be6027e1378 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 11 Aug 2012 18:20:28 -0400 Subject: [PATCH] [OT] Add shape_plan to Arabic shaper --- src/hb-ot-shape-complex-arabic.cc | 82 +++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 2a96b7d..e0db41c 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Google, Inc. + * Copyright © 2010,2012 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -99,7 +99,7 @@ static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second) return 0; } -static const hb_tag_t arabic_syriac_features[] = +static const hb_tag_t arabic_features[] = { HB_TAG('i','n','i','t'), HB_TAG('m','e','d','i'), @@ -127,9 +127,7 @@ enum { NONE, - COMMON_NUM_FEATURES = 4, - SYRIAC_NUM_FEATURES = 7, - TOTAL_NUM_FEATURES = NONE + ARABIC_NUM_FEATURES = NONE }; static const struct arabic_state_table_entry { @@ -184,9 +182,8 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_gsub_pause (NULL); - unsigned int num_features = plan->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES; - for (unsigned int i = 0; i < num_features; i++) - map->add_bool_feature (arabic_syriac_features[i], false); + for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) + map->add_bool_feature (arabic_features[i], false); map->add_gsub_pause (NULL); @@ -200,10 +197,51 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_bool_feature (HB_TAG('c','s','w','h')); } +struct arabic_shape_plan_t +{ + ASSERT_POD (); + + bool do_fallback; + hb_mask_t mask_array[ARABIC_NUM_FEATURES]; +}; + +static void * +data_create_arabic (const hb_ot_shape_plan_t *plan) +{ + arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t)); + if (unlikely (!arabic_plan)) + return NULL; + + hb_mask_t total_masks = 0; + for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { + arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]); + total_masks |= arabic_plan->mask_array[i]; + } + + /* Pitfalls: + * - This path fires if user force-set init/medi/fina/isol off, + * - If font does not declare script 'arab', well, what to do? + * Most probably it's safe to assume that init/medi/fina/isol + * still mean Arabic shaping, although they do not have to. + */ + arabic_plan->do_fallback = 0 == total_masks; + + return arabic_plan; +} + +static void +data_destroy_arabic (void *data) +{ + free (data); +} static void arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer) { + /* Only Arabic has presentation forms encoded in Unicode. */ + if (buffer->props.script != HB_SCRIPT_ARABIC) + return; + unsigned int count = buffer->len; hb_codepoint_t glyph; @@ -240,6 +278,8 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, hb_font_t *font) { + const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; + unsigned int count = buffer->len; unsigned int prev = 0, state = 0; @@ -265,28 +305,12 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, state = entry->next_state; } - hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0}; - hb_mask_t total_masks = 0; - unsigned int num_masks = buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES; - for (unsigned int i = 0; i < num_masks; i++) { - mask_array[i] = plan->map.get_1_mask (arabic_syriac_features[i]); - total_masks |= mask_array[i]; - } - - if (total_masks) { + if (likely (!arabic_plan->do_fallback)) { /* Has OpenType tables */ for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()]; - } else if (buffer->props.script == HB_SCRIPT_ARABIC) { - /* Fallback Arabic shaping to Presentation Forms */ - /* Pitfalls: - * - This path fires if user force-set init/medi/fina/isol off, - * - If font does not declare script 'arab', well, what to do? - * Most probably it's safe to assume that init/medi/fina/isol - * still mean Arabic shaping, although they do not have to. - */ + buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()]; + } else arabic_fallback_shape (font, buffer); - } HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } @@ -296,8 +320,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = "arabic", collect_features_arabic, NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ + data_create_arabic, + data_destroy_arabic, NULL, /* normalization_preference */ setup_masks_arabic, true, /* zero_width_attached_marks */ -- 2.7.4