From 2fcbbdb41a322f54b61d9ce983ab54434504c5ed Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 29 Aug 2012 11:11:54 -0400 Subject: [PATCH] Port Arabic fallback ligating to share code with GSUB This will eventually allow us to skip marks, as well as (fallback) attach marks to ligature components of fallback-shaped Arabic. That would be pretty cool. I kludged GDEF props in, so mark-skipping works, but the produced ligature id/components will be cleared later by substitute_start() et al. Perhaps using a synthetic table for Arabic fallback shaping was a better idea. The current approach has way too many layering violations... --- src/hb-ot-layout-gsubgpos-private.hh | 4 ++ src/hb-ot-shape-complex-arabic.cc | 72 ++++++++++++++++++++++++------------ src/hb-ot-shape.cc | 4 +- 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 5815d5f..00bc563 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -134,6 +134,10 @@ struct hb_apply_context_t has_glyph_classes (gdef.has_glyph_classes ()), digest (*digest_) {} + void set_lookup_props (unsigned int lookup_props_) { + lookup_props = lookup_props_; + } + void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 857bf55..965947a 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -26,7 +26,7 @@ #include "hb-ot-shape-complex-private.hh" #include "hb-ot-shape-private.hh" - +#include "hb-ot-layout-gsubgpos-private.hh" /* buffer var allocations */ @@ -88,17 +88,6 @@ static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape) return u; } -static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second) -{ - if (unlikely (!second)) return 0; - for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++) - if (ligature_table[i].first == first) - for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++) - if (ligature_table[i].ligatures[j].second == second) - return ligature_table[i].ligatures[j].ligature; - return 0; -} - static const hb_tag_t arabic_features[] = { HB_TAG('i','n','i','t'), @@ -257,20 +246,57 @@ arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer) buffer->info[i].codepoint = shaped; } + OT::hb_apply_context_t c (font, buffer, 1/*global mask*/, NULL); + c.set_lookup_props (OT::LookupFlag::IgnoreMarks); + /* Mandatory ligatures */ buffer->clear_output (); - for (buffer->idx = 0; buffer->idx + 1 < count;) { - hb_codepoint_t ligature = get_ligature (buffer->cur().codepoint, - buffer->cur(+1).codepoint); - if (likely (!ligature) || !(font->get_glyph (ligature, 0, &glyph))) { - buffer->next_glyph (); - continue; + for (buffer->idx = 0; buffer->idx + 1 < count;) + { + const unsigned int count = 2; + unsigned int end_offset; + bool is_mark_ligature; + unsigned int total_component_count; + + bool matched = false; + for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++) + { + if (ligature_table[i].first != buffer->cur().codepoint) + continue; + for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++) + { + OT::USHORT component; + component.set (ligature_table[i].ligatures[j].second); + hb_codepoint_t ligature = ligature_table[i].ligatures[j].ligature; + if (likely (!OT::match_input (&c, count, + &component, + OT::match_glyph, + NULL, + &end_offset, + &is_mark_ligature, + &total_component_count) || + !(font->get_glyph (ligature, 0, &glyph)))) + continue; + + /* Deal, we are forming the ligature. */ + buffer->merge_clusters (buffer->idx, buffer->idx + end_offset); + + OT::ligate_input (&c, + count, + &component, + ligature, + OT::match_glyph, + NULL, + is_mark_ligature, + total_component_count); + matched = true; + break; + } + if (matched) + break; } - - buffer->replace_glyphs (2, 1, &ligature); - - /* Technically speaking we can skip marks and stuff, like the GSUB path does. - * But who cares, we're in fallback! */ + if (!matched) + buffer->next_glyph (); } for (; buffer->idx < count;) buffer->next_glyph (); diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 29076cf..009a25d 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -319,8 +319,10 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer) static inline void hb_ot_substitute_default (hb_ot_shape_context_t *c) { - if (c->plan->shaper->preprocess_text) + if (c->plan->shaper->preprocess_text) { + hb_synthesize_glyph_classes (c); /* XXX This is a hack for now. */ c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); + } hb_ot_mirror_chars (c); -- 2.7.4