return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
}
-int
-OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
- const char *script, const char *language,
- const char *feature)
+static int
+iterate_coverage (OTF *otf, const char *feature,
+ OTF_Feature_Callback callback,
+ OTF_Coverage *coverage)
{
- char *errfmt = "GSUB iterate feature%s";
- int errret = -1;
- int i, j, k, l, m;
+ int i;
- OTF_GSUB *gsub;
- OTF_LangSys *langsys;
- char *lookup_flags;
+ if (coverage->CoverageFormat == 1)
+ {
+ for (i = 0; i < coverage->Count; i++)
+ if (callback (otf, feature, coverage->table.GlyphArray[i]) < 0)
+ return -1;
+ }
+ else
+ {
+ for (i = 0; i < coverage->Count; i++)
+ {
+ OTF_RangeRecord *range = coverage->table.RangeRecord + i;
+ unsigned id;
+ for (id = range->Start; id <= range->End; id++)
+ if (callback (otf, feature, id) < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
- if (OTF_get_table (otf, "GSUB") < 0)
- return errret;
- gsub = otf->gsub;
- if (gsub->FeatureList.FeatureCount == 0
- || gsub->LookupList.LookupCount == 0)
- return 0;
- langsys = get_langsys (&gsub->ScriptList, script, language);
- if (! langsys)
- return errret;
- lookup_flags = alloca (gsub->LookupList.LookupCount);
- if (! lookup_flags
- || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
- feature, lookup_flags) < 0)
- OTF_ERROR (OTF_ERROR_MEMORY, " feature");
+static int
+iterate_feature (OTF *otf, const char *feature,
+ OTF_Feature_Callback callback,
+ OTF_Lookup *lookup)
+{
+ int i, j, k, l;
- for (i = 0; i < gsub->LookupList.LookupCount; i++)
+ for (i = 0; i < lookup->SubTableCount; i++)
{
- OTF_Lookup *lookup;
+ unsigned lookup_type = lookup->LookupType;
+ OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
- if (! lookup_flags[i]) continue;
- lookup = gsub->LookupList.Lookup + i;
- for (j = 0; j < lookup->SubTableCount; j++)
+ if (lookup_type == 7)
{
- unsigned lookup_type = lookup->LookupType;
- OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + j;
- int coverage_idx;
+ OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
- if (lookup_type == 7)
- {
- OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
+ lookup_type = extension1->ExtensionLookupType;
+ subtable = extension1->ExtensionSubtable;
+ }
- lookup_type = extension1->ExtensionLookupType;
- subtable = extension1->ExtensionSubtable;
- }
- if ((lookup_type >= 1 && lookup_type <= 4) || lookup_type == 8)
+ if ((lookup_type >= 1 && lookup_type <= 3) || lookup_type == 8)
+ {
+ if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
+ < 0)
+ return -1;
+ }
+ else if (lookup_type == 4)
+ {
+ OTF_GSUB_Ligature1 *lig1;
+
+ if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
+ < 0)
+ return -1;
+ lig1 = &subtable->u.ligature1;
+ for (j = 0; j < lig1->LigSetCount; j++)
{
- OTF_Coverage *coverage = &subtable->Coverage;
+ OTF_LigatureSet *ligset = lig1->LigatureSet + j;
- if (coverage->CoverageFormat == 1)
+ for (k = 0; k < ligset->LigatureCount; k++)
{
- for (k = 0; k < coverage->Count; k++)
- {
- unsigned id = coverage->table.GlyphArray[k];
- int c = OTF_get_unicode (otf, id);
- if (callback (otf, feature, c, id) < 0)
- return 0;
- }
+ OTF_Ligature *lig = ligset->Ligature + k;
+ for (l = 0; l < lig->CompCount - 1; l++)
+ if (callback (otf, feature, lig->Component[l]) < 0)
+ return -1;
}
- else
+ }
+ }
+ else if (lookup_type == 6)
+ {
+ if (subtable->Format == 1)
+ {
+ OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
+ for (j = 0; j < context1->ChainRuleSetCount; j++)
{
- for (k = 0; k < coverage->Count; k++)
+ OTF_ChainRuleSet *set = context1->ChainRuleSet + j;
+ for (k = 0; k < set->ChainRuleCount; k++)
{
- OTF_RangeRecord *range = coverage->table.RangeRecord + k;
- unsigned id;
- for (id = range->Start; id <= range->End; id++)
+ OTF_ChainRule *rule = set->ChainRule + k;
+ for (l = 0; l < rule->LookupCount; l++)
{
- int c = OTF_get_unicode (otf, id);
- if (callback (otf, feature, c, id) < 0)
- return 0;
+ OTF_Lookup *lkup
+ = (otf->gsub->LookupList.Lookup
+ + rule->LookupRecord[l].LookupListIndex);
+ if (iterate_feature (otf, feature, callback, lkup)
+ < 0)
+ return -1;
}
}
}
+ }
+ else if (subtable->Format == 2)
+ {
+ OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
- if (lookup_type == 4)
+ for (j = 0; j < context2->ChainClassSetCnt; j++)
{
- OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
-
- for (k = 0; k < lig1->LigSetCount; k++)
+ OTF_ChainClassSet *set = context2->ChainClassSet + j;
+ for (k = 0; k < set->ChainClassRuleCnt; j++)
{
- OTF_LigatureSet *ligset = lig1->LigatureSet + k;
+ OTF_ChainClassRule *rule = set->ChainClassRule + k;
- for (l = 0; l < ligset->LigatureCount; l++)
+ for (l = 0; l < rule->LookupCount; l++)
{
- OTF_Ligature *lig = ligset->Ligature + l;
- for (m = 0; m < lig->CompCount - 1; m++)
- {
- unsigned id = lig->Component[m];
- int c = OTF_get_unicode (otf, id);
- if (callback (otf, feature, c, id) < 0)
- return 0;
- }
+ OTF_Lookup *lkup
+ = (otf->gsub->LookupList.Lookup
+ + rule->LookupRecord[k].LookupListIndex);
+ if (iterate_feature (otf, feature, callback, lkup)
+ < 0)
+ return -1;
}
}
}
}
+ else
+ {
+ OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
+ for (j = 0; j < context3->LookupCount; j++)
+ {
+ OTF_Lookup *lkup
+ = (otf->gsub->LookupList.Lookup
+ + context3->LookupRecord[j].LookupListIndex);
+ if (iterate_feature (otf, feature, callback, lkup) < 0)
+ return -1;
+ }
+ }
}
}
+ return 0;
+}
+
+int
+OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
+ const char *script, const char *language,
+ const char *feature)
+{
+ char *errfmt = "GSUB iterate feature%s";
+ int errret = -1;
+ int i;
+
+ OTF_GSUB *gsub;
+ OTF_LangSys *langsys;
+ char *lookup_flags;
+
+ if (OTF_get_table (otf, "GSUB") < 0)
+ return errret;
+ gsub = otf->gsub;
+ if (gsub->FeatureList.FeatureCount == 0
+ || gsub->LookupList.LookupCount == 0)
+ return 0;
+ langsys = get_langsys (&gsub->ScriptList, script, language);
+ if (! langsys)
+ return errret;
+ lookup_flags = alloca (gsub->LookupList.LookupCount);
+ if (! lookup_flags
+ || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
+ feature, lookup_flags) < 0)
+ OTF_ERROR (OTF_ERROR_MEMORY, " feature");
+
+ for (i = 0; i < gsub->LookupList.LookupCount; i++)
+ if (lookup_flags[i])
+ if (iterate_feature (otf, feature, callback, gsub->LookupList.Lookup + i)
+ < 0)
+ return -1;
+ return 0;
}