From 851784f8372004e0a40b698c0cdc2d7db8629aa2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 14 Nov 2012 16:24:05 -0800 Subject: [PATCH] Improve shaper selection --- src/hb-ot-map-private.hh | 8 ++++---- src/hb-ot-map.cc | 6 ++++-- src/hb-ot-shape-complex-indic.cc | 2 +- src/hb-ot-shape-complex-private.hh | 13 ++++++++----- src/hb-ot-shape-complex-thai.cc | 26 +++++++++++++++++++++++--- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 11d97e1d5..c7dbea5e0 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -115,9 +115,6 @@ struct hb_ot_map_t *lookup_count = end - start; } - inline hb_tag_t get_chosen_script (unsigned int table_index) const - { return chosen_script[table_index]; } - HB_INTERNAL void substitute_closure (const struct hb_ot_shape_plan_t *plan, hb_face_t *face, hb_set_t *glyphs) const; HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; @@ -130,6 +127,9 @@ struct hb_ot_map_t pauses[1].finish (); } + public: + hb_tag_t chosen_script[2]; + bool found_script[2]; private: @@ -140,7 +140,6 @@ struct hb_ot_map_t hb_mask_t global_mask; - hb_tag_t chosen_script[2]; hb_prealloced_array_t features; hb_prealloced_array_t lookups[2]; /* GSUB/GPOS */ hb_prealloced_array_t pauses[2]; /* GSUB/GPOS */ @@ -200,6 +199,7 @@ struct hb_ot_map_builder_t hb_segment_properties_t props; hb_tag_t chosen_script[2]; + bool found_script[2]; unsigned int script_index[2], language_index[2]; private: diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 046fa97e3..024b7dfc4 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -79,7 +79,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, for (unsigned int table_index = 0; table_index < 2; table_index++) { hb_tag_t table_tag = table_tags[table_index]; - hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); + found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]); hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); } } @@ -161,8 +161,10 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { m.global_mask = 1; - for (unsigned int table_index = 0; table_index < 2; table_index++) + for (unsigned int table_index = 0; table_index < 2; table_index++) { m.chosen_script[table_index] = chosen_script[table_index]; + m.found_script[table_index] = found_script[table_index]; + } if (!feature_infos.len) return; diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index a7f9b60ce..324a04b94 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -329,7 +329,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan) break; } - indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.get_chosen_script (0) & 0x000000FF) != '2'); + indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2'); indic_plan->virama_glyph = (hb_codepoint_t) -1; indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f')); diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index 043e8e3b3..9f8cecdb6 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -278,15 +278,18 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_TAKRI: /* Only use Indic shaper if the font has Indic tables. */ - if (planner->map.chosen_script[0] == HB_OT_TAG_DEFAULT_SCRIPT) - return &_hb_ot_complex_shaper_default; - else + if (planner->map.found_script[0]) return &_hb_ot_complex_shaper_indic; + else + return &_hb_ot_complex_shaper_default; case HB_SCRIPT_KHMER: /* If the font has 'liga', let the generic shaper do it. */ - if (planner->map.chosen_script[0] == HB_OT_TAG_DEFAULT_SCRIPT || - hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB, planner->map.script_index[0], planner->map.language_index[0], HB_TAG ('l','i','g','a'), NULL)) + if (!planner->map.found_script[0] || + hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB, + planner->map.script_index[0], + planner->map.language_index[0], + HB_TAG ('l','i','g','a'), NULL)) return &_hb_ot_complex_shaper_default; else return &_hb_ot_complex_shaper_indic; diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index d6f466973..0736ecaac 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -30,10 +30,26 @@ /* Thai / Lao shaper */ static void -preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_buffer_t *buffer, - hb_font_t *font HB_UNUSED) +do_thai_pua_shaping (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) { +} + +static void +preprocess_text_thai (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + /* This function implements the shaping logic documented here: + * + * http://linux.thai.net/~thep/th-otf/shaping.html + * + * The first shaping rule listed there is needed even if the font has Thai + * OpenType tables. The rest do fallback positioning based on PUA codepoints. + * We implement that only if there exist no Thai GSUB in the font. + */ + /* The following is NOT specified in the MS OT Thai spec, however, it seems * to be what Uniscribe and other engines implement. According to Eric Muller: * @@ -122,6 +138,10 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED, } } buffer->swap_buffers (); + + /* If font has Thai GSUB, we are done. */ + if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0]) + do_thai_pua_shaping (plan, buffer, font); } const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =