From 3d84a6eafd9de57d1bc1f8cd3f5edb0590eef747 Mon Sep 17 00:00:00 2001 From: handa Date: Wed, 4 Aug 2004 04:23:06 +0000 Subject: [PATCH] (gstring_subst): New arg flag. Caller changed. Ignore glyphs specified in flag. (match_ids, match_classes, match_coverages): Likewise. (match_chain_ids, match_chain_classes, match_chain_coverages): New arg flag. (lookup_gsub): Fix handling of LookupFlag. (lookup_gpos): Likewise. Support more LookupType. --- src/otfdrive.c | 246 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 187 insertions(+), 59 deletions(-) diff --git a/src/otfdrive.c b/src/otfdrive.c index b522d75..c5ec6af 100644 --- a/src/otfdrive.c +++ b/src/otfdrive.c @@ -56,7 +56,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite static int -gstring_subst (OTF_GlyphString *gstring, int from, int to, +gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag, OTF_GlyphID *ids, int num) { int errret = -1; @@ -65,6 +65,18 @@ gstring_subst (OTF_GlyphString *gstring, int from, int to, int c = gstring->glyphs[from].c; int from_idx = gstring->glyphs[from].f.index.from; int to_idx = gstring->glyphs[to - 1].f.index.to; + int non_ignored_idx; + + for (i = non_ignored_idx = to - 1; i >= from; i--) + if (flag & (1 << gstring->glyphs[i].GlyphClass)) + { + OTF_Glyph temp = gstring->glyphs[i]; + + memmove (gstring->glyphs + i, gstring->glyphs + i + 1, + sizeof (OTF_Glyph) * (non_ignored_idx - i)); + non_ignored_idx--; + len--; + } if (len < num) GSTRING_INSERT (gstring, from, (num - len)); @@ -230,7 +242,8 @@ setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList, } static int -match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids) +match_ids (OTF_GlyphString *gstring, int gidx, int flag, + int count, OTF_GlyphID *ids) { OTF_Glyph *gbeg = gstring->glyphs + gidx; OTF_Glyph *gend = gstring->glyphs + gstring->used; @@ -238,13 +251,15 @@ match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids) int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id && g->glyph_id != ids[i++]) + if (g->glyph_id && ! (flag & (1 << g->GlyphClass)) + && g->glyph_id != ids[i++]) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule) +match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag, + OTF_ChainRule *rule) { int i = rule->BacktrackGlyphCount; @@ -258,16 +273,19 @@ match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule) break; if (i > 0) return -1; - if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack) + if (match_ids (gstring, j, flag, + rule->BacktrackGlyphCount, rule->Backtrack) < 0) return -1; } gidx++; - i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input); + i = match_ids (gstring, gidx, flag, + rule->InputGlyphCount - 1, rule->Input); if (i < 0) return -1; gidx += i; - i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead); + i = match_ids (gstring, gidx, flag, + rule->LookaheadGlyphCount, rule->LookAhead); if (i < 0) return -1; return 0; @@ -275,7 +293,7 @@ match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule) static int match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx, - int count, unsigned *classes) + int flag, int count, unsigned *classes) { OTF_Glyph *gbeg = gstring->glyphs + gidx; OTF_Glyph *gend = gstring->glyphs + gstring->used; @@ -283,14 +301,14 @@ match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx, int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id + if (g->glyph_id && ! (flag & (1 << g->GlyphClass)) && get_class_def (class_def, g->glyph_id) != classes[i++]) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_classes (OTF_GlyphString *gstring, int gidx, +match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag, OTF_ClassDef *BacktrackClassDef, OTF_ClassDef *InputClassDef, OTF_ClassDef *LookaheadClassDef, @@ -308,17 +326,17 @@ match_chain_classes (OTF_GlyphString *gstring, int gidx, break; if (i > 0) return -1; - if (match_classes (BacktrackClassDef, gstring, j, + if (match_classes (BacktrackClassDef, gstring, j, flag, rule->BacktrackGlyphCount, rule->Backtrack) < 0); return -1; } gidx++; - i = match_classes (InputClassDef, gstring, gidx, + i = match_classes (InputClassDef, gstring, gidx, flag, rule->InputGlyphCount - 1, rule->Input); if (i < 0) return -1; gidx += i; - i = match_classes (LookaheadClassDef, gstring, gidx, + i = match_classes (LookaheadClassDef, gstring, gidx, flag, rule->LookaheadGlyphCount, rule->LookAhead); if (i < 0) return -1; @@ -327,7 +345,7 @@ match_chain_classes (OTF_GlyphString *gstring, int gidx, static int -match_coverages (OTF_GlyphString *gstring, int gidx, int count, +match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count, OTF_Coverage *coverages) { OTF_Glyph *gbeg = gstring->glyphs + gidx; @@ -336,14 +354,14 @@ match_coverages (OTF_GlyphString *gstring, int gidx, int count, int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id + if (g->glyph_id && ! (flag & (1 << g->GlyphClass)) && get_coverage_index (coverages + i++, g->glyph_id) < 0) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_coverages (OTF_GlyphString *gstring, int gidx, +match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag, OTF_GSUB_ChainContext3 *context3) { int i = context3->BacktrackGlyphCount; @@ -358,20 +376,20 @@ match_chain_coverages (OTF_GlyphString *gstring, int gidx, break; if (i > 0) return -1; - if (match_coverages (gstring, j, context3->BacktrackGlyphCount, + if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount, context3->Backtrack) < 0) return -1; } gidx++; if (context3->InputGlyphCount > 1) { - i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1, + i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1, context3->Input + 1); if (i < 0) return -1; gidx += i; } - if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount, + if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount, context3->LookAhead) < 0) return -1; return 0; @@ -384,7 +402,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, char *errfmt = "GSUB Looking up%s"; int errret = -1; OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index; - unsigned int flag = lookup->LookupFlag; + unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask; int orig_gidx = gidx; OTF_Glyph *g = gstring->glyphs + gidx; int i; @@ -432,13 +450,15 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1; OTF_Sequence *seq = multiple1->Sequence + coverage_idx; - gstring_subst (gstring, gidx, gidx + 1, + gstring_subst (gstring, gidx, gidx + 1, flag, seq->Substitute, seq->GlyphCount); gidx += seq->GlyphCount; } break; case 3: + /* For the moment, we always ignore this feature. */ + break; if (subtable->Format == 1) { OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1; @@ -464,11 +484,11 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int n; lig = ligset->Ligature + j; - n = match_ids (gstring, gidx + 1, + n = match_ids (gstring, gidx + 1, flag, lig->CompCount - 1, lig->Component); if (n < 0) continue; - gstring_subst (gstring, gidx, gidx + 1 + n, + gstring_subst (gstring, gidx, gidx + 1 + n, flag, &lig->LigGlyph, 1); gidx++; break; @@ -490,7 +510,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, for (j = 0; j < set->RuleCount; j++) { rule = set->Rule + j; - if (match_ids (gstring, gidx + 1, + if (match_ids (gstring, gidx + 1, flag, rule->GlyphCount - 1, rule->Input) < 0) continue; orig_used = gstring->used; @@ -519,7 +539,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, { rule = set->ClassRule + j; if (match_classes (&context2->ClassDef, - gstring, gidx + 1, + gstring, gidx + 1, flag, rule->GlyphCount - 1, rule->Class) < 0) continue; @@ -539,7 +559,8 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int orig_used; int j; - if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1, + if (match_coverages (gstring, gidx + 1, flag, + context3->GlyphCount - 1, context3->Coverage + 1) < 0) continue; orig_used = gstring->used; @@ -568,7 +589,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - if (match_chain_ids (gstring, gidx, rule) < 0) + if (match_chain_ids (gstring, gidx, flag, rule) < 0) continue; orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) @@ -599,7 +620,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - if (match_chain_classes (gstring, gidx, + if (match_chain_classes (gstring, gidx, flag, &context2->BacktrackClassDef, &context2->InputClassDef, &context2->LookaheadClassDef, @@ -625,7 +646,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, || (gidx + context3->InputGlyphCount + context3->LookaheadGlyphCount) > gstring->used) continue; - if (match_chain_coverages (gstring, gidx, context3) < 0) + if (match_chain_coverages (gstring, gidx, flag, context3) < 0) continue; orig_used = gstring->used; for (j = 0; j < context3->LookupCount; j++) @@ -704,7 +725,7 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, char *errfmt = "GPOS Looking up%s"; int errret = -1; OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index; - unsigned int flag = lookup->LookupFlag; + unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask; int orig_gidx = gidx; OTF_Glyph *g = gstring->glyphs + gidx; int i; @@ -755,7 +776,9 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_Glyph *nextg; while (next_gidx < gstring->used - && ! gstring->glyphs[next_gidx].glyph_id) + && (! gstring->glyphs[next_gidx].glyph_id + || ! (flag + & (1 << gstring->glyphs[next_gidx].GlyphClass)))) next_gidx++; if (next_gidx >= gstring->used) @@ -873,10 +896,18 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1; OTF_MarkRecord *mark1_record; OTF_AnchorRecord *mark2_record; - int coverage_idx_base + OTF_Glyph *prevg = g - 1; + int coverage_idx_base; + + while (prevg >= gstring->glyphs + && (! prevg->glyph_id + || ! (flag & (1 << prevg->GlyphClass)))) + prevg--; + if (prevg < gstring->glyphs) + continue; + coverage_idx_base = get_coverage_index (&mark_mark1->Mark2Coverage, - g[-1].glyph_id); - + prevg->glyph_id); if (coverage_idx_base < 0) continue; mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx; @@ -891,12 +922,108 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, break; case 7: - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + if (subtable->Format == 1) + { + OTF_GPOS_Context1 *context1 = &subtable->u.context1; + OTF_RuleSet *set = context1->RuleSet + coverage_idx; + OTF_Rule *rule; + int orig_used; + int j, k; + + for (j = 0; j < set->RuleCount; j++) + { + rule = set->Rule + j; + if (match_ids (gstring, gidx + 1, flag, + rule->GlyphCount - 1, rule->Input) < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else if (subtable->Format == 2) + { + OTF_GPOS_Context2 *context2 = &subtable->u.context2; + OTF_ClassSet *set; + OTF_ClassRule *rule; + unsigned class; + int orig_used; + int j, k; + + class = get_class_def (&context2->ClassDef, g->glyph_id); + set = context2->ClassSet + class; + if (set) + for (j = 0; j < set->ClassRuleCnt; j++) + { + rule = set->ClassRule + j; + if (match_classes (&context2->ClassDef, + gstring, gidx + 1, flag, + rule->GlyphCount - 1, rule->Class) + < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else /* subtable->Format == 3 */ + { + OTF_GPOS_Context3 *context3 = &subtable->u.context3; + int orig_used; + int j; + + if (match_coverages (gstring, gidx + 1, flag, + context3->GlyphCount - 1, + context3->Coverage + 1) < 0) + continue; + orig_used = gstring->used; + for (j = 0; j < context3->LookupCount; j++) + lookup_gpos (lookup_list, + context3->LookupRecord[j].LookupListIndex, + gstring, + gidx + context3->LookupRecord[j].SequenceIndex); + gidx += context3->GlyphCount + (gstring->used - orig_used); + } break; case 8: if (subtable->Format == 1) - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + { + OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1; + OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx; + int orig_used; + int j, k; + + for (j = 0; j < set->ChainRuleCount; j++) + { + OTF_ChainRule *rule = set->ChainRule + j; + + if (gidx < rule->BacktrackGlyphCount + || (gidx + rule->InputGlyphCount + + rule->LookaheadGlyphCount) > gstring->used) + continue; + if (match_chain_ids (gstring, gidx, flag, rule) < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->InputGlyphCount + (gstring->used - orig_used); + break; + } + } else if (subtable->Format == 2) { OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2; @@ -910,35 +1037,18 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, for (j = 0; j < set->ChainClassRuleCnt; j++) { OTF_ChainClassRule *rule = set->ChainClassRule + j; - int fore_idx = gidx + rule->InputGlyphCount; int k; if (gidx < rule->BacktrackGlyphCount || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - for (k = 0; k < rule->BacktrackGlyphCount; k++) - if (get_class_def (&context2->BacktrackClassDef, - gstring->glyphs[gidx - 1 - k].glyph_id) - != rule->Backtrack[k]) - break; - if (k < rule->BacktrackGlyphCount) - continue; - for (k = 1; k < rule->InputGlyphCount; k++) - if (get_class_def (&context2->InputClassDef, - gstring->glyphs[gidx + k].glyph_id) - != rule->Input[k - 1]) - break; - if (k < rule->InputGlyphCount) - continue; - for (k = 0; k < rule->LookaheadGlyphCount; k++) - if (get_class_def (&context2->LookaheadClassDef, - gstring->glyphs[fore_idx + k].glyph_id) - != rule->LookAhead[k]) - break; - if (k < rule->LookaheadGlyphCount) + if (match_chain_classes (gstring, gidx, flag, + &context2->BacktrackClassDef, + &context2->InputClassDef, + &context2->LookaheadClassDef, + rule) < 0) continue; - orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) lookup_gpos (lookup_list, @@ -950,7 +1060,25 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, } } else if (subtable->Format == 3) - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + { + OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3; + int orig_used; + int j; + + if (gidx < context3->BacktrackGlyphCount + || (gidx + context3->InputGlyphCount + + context3->LookaheadGlyphCount) > gstring->used) + continue; + if (match_chain_coverages (gstring, gidx, flag, context3) < 0) + continue; + orig_used = gstring->used; + for (j = 0; j < context3->LookupCount; j++) + lookup_gpos (lookup_list, + context3->LookupRecord[j].LookupListIndex, + gstring, + gidx + context3->LookupRecord[j].SequenceIndex); + gidx += context3->InputGlyphCount + (gstring->used - orig_used); + } else OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)"); break; -- 1.7.10.4