[OTLayout] Correctly skip Default_Ignorable when match_func not set

When a match_func was not set on the matcher_t object (ie. from GPOS),
then the Default_Ignorables (including joiners) were never skipped.
This meant that they were not skipped as they should during GPOS
matching.  Fix that.

A few Indic numbers have "regressed": BENGALI and DEVANAGARI went
up from 290 and 58 respectively, but in both cases new results are
superior to Uniscribe, as they apply GPOS when we weren't (and
Uniscribe isn't) before.
BENGALI: 353686 out of 354188 tests passed. 502 failed (0.141733%)
DEVANAGARI: 707305 out of 707394 tests passed. 89 failed (0.0125814%)
GUJARATI: 366262 out of 366457 tests passed. 195 failed (0.0532122%)
GURMUKHI: 60706 out of 60747 tests passed. 41 failed (0.067493%)
KANNADA: 950680 out of 951913 tests passed. 1233 failed (0.129529%)
KHMER: 299074 out of 299124 tests passed. 50 failed (0.0167155%)
LAO: 53611 out of 53644 tests passed. 33 failed (0.0615167%)
MALAYALAM: 1047983 out of 1048334 tests passed. 351 failed (0.0334817%)
ORIYA: 42320 out of 42329 tests passed. 9 failed (0.021262%)
SINHALA: 271539 out of 271847 tests passed. 308 failed (0.113299%)
TAMIL: 1091753 out of 1091754 tests passed. 1 failed (9.15957e-05%)
TELUGU: 970555 out of 970573 tests passed. 18 failed (0.00185457%)
TIBETAN: 208469 out of 208469 tests passed. 0 failed (0%)
This commit is contained in:
Behdad Esfahbod 2013-02-21 15:07:03 -05:00
parent ff93ac8cb2
commit 2b2a6e8944
1 changed files with 22 additions and 10 deletions

View File

@ -315,12 +315,23 @@ struct hb_apply_context_t
const void *match_data_) const void *match_data_)
{ match_func = match_func_; match_data = match_data_; } { match_func = match_func_; match_data = match_data_; }
inline bool matches (const hb_glyph_info_t &info, enum may_match_t {
const USHORT *glyph_data) const MATCH_NO,
MATCH_YES,
MATCH_MAYBE
};
inline may_match_t may_match (const hb_glyph_info_t &info,
const USHORT *glyph_data) const
{ {
return (info.mask & mask) && if (!(info.mask & mask) ||
(!syllable || syllable == info.syllable ()) && (syllable && syllable != info.syllable ()))
(!match_func || match_func (info.codepoint, *glyph_data, match_data)); return MATCH_NO;
if (match_func)
return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
} }
enum may_skip_t { enum may_skip_t {
@ -405,11 +416,11 @@ struct hb_apply_context_t
const hb_glyph_info_t &info = c->buffer->info[idx]; const hb_glyph_info_t &info = c->buffer->info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info); matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES)) if (unlikely (skip == matcher_t::SKIP_YES))
continue; continue;
if (matcher.matches (info, match_glyph_data)) matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
if (unlikely (match == matcher_t::MATCH_YES))
{ {
num_items--; num_items--;
match_glyph_data++; match_glyph_data++;
@ -417,7 +428,7 @@ struct hb_apply_context_t
} }
if (skip == matcher_t::SKIP_NO) if (skip == matcher_t::SKIP_NO)
return false; return match == matcher_t::MATCH_MAYBE ? true : false;
} }
return false; return false;
} }
@ -481,7 +492,8 @@ struct hb_apply_context_t
if (unlikely (skip == matcher_t::SKIP_YES)) if (unlikely (skip == matcher_t::SKIP_YES))
continue; continue;
if (matcher.matches (info, match_glyph_data)) matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
if (unlikely (match == matcher_t::MATCH_YES))
{ {
num_items--; num_items--;
match_glyph_data++; match_glyph_data++;
@ -489,7 +501,7 @@ struct hb_apply_context_t
} }
if (skip == matcher_t::SKIP_NO) if (skip == matcher_t::SKIP_NO)
return false; return match == matcher_t::MATCH_MAYBE ? true : false;
} }
return false; return false;
} }