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;
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));
}
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;
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;
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;
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;
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,
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;
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;
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;
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;
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;
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;
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;
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;
{
rule = set->ClassRule + j;
if (match_classes (&context2->ClassDef,
- gstring, gidx + 1,
+ gstring, gidx + 1, flag,
rule->GlyphCount - 1, rule->Class)
< 0)
continue;
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;
|| (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++)
|| (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,
|| (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++)
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;
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)
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;
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;
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,
}
}
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;