printf("</cmap_format_%d>\n", format);
}
+static int
+compare_features_by_tag(const void *va, const void *vb)
+{
+ struct gsub_feature const * const *ap = va, * const *bp = vb;
+
+ return namecmp((*ap)->tag, (*bp)->tag);
+}
+
static void
dogsub(void)
{
int i, j;
+ struct gsub_feature const *sorted[lenof(gsub_features)];
+ for (i = 0; i < lenof(gsub_features); i++)
+ sorted[i] = &gsub_features[i];
+ qsort(sorted, lenof(sorted), sizeof(sorted[0]),
+ &compare_features_by_tag);
printf("<GSUB>\n");
TTXS("Version", "0x00010000");
printf("<ScriptList>\n");
+ /*
+ * The FeatureList should be sorted alphabetically by tag, but
+ * the LookupList has to be in the order in which the lookups
+ * should be applied. The FeatureIndices can be in any order
+ * we like. This requires some care with the indexing.
+ */
for (i = 0; i < lenof(gsub_scripts); i++) {
printf("<ScriptRecord>\n");
TTXS("ScriptTag", gsub_scripts[i].tag);
printf("<Script><DefaultLangSys>\n");
TTXI("ReqFeatureIndex", 0xffff); /* No required feature. */
- for (j = 0; j < lenof(gsub_features); j++)
- if (gsub_features[j].scripts & gsub_scripts[i].flag) {
- printf("<!-- %s --> ", gsub_features[j].tag);
+ for (j = 0; j < lenof(sorted); j++)
+ if (sorted[j]->scripts & gsub_scripts[i].flag) {
+ printf("<!-- %s --> ", sorted[j]->tag);
TTXI("FeatureIndex", j);
}
printf("</DefaultLangSys></Script>\n");
}
printf("</ScriptList>\n");
printf("<FeatureList>\n");
- for (i = 0; i < lenof(gsub_features); i++) {
+ for (i = 0; i < lenof(sorted); i++) {
+ struct gsub_feature const *feat = sorted[i];
+ int featidx = (feat - gsub_features);
printf("<FeatureRecord>\n");
- TTXS("FeatureTag", gsub_features[i].tag);
+ TTXS("FeatureTag", feat->tag);
printf("<Feature>\n");
- if (gsub_features[i].name != NULL) {
- if (gsub_features[i].tag[0] == 's') {
+ if (feat->name != NULL) {
+ if (feat->tag[0] == 's') {
printf("<FeatureParamsStylisticSet>\n");
TTXI("Version", 0);
- TTXI("UINameID", NAMEBASE_GSUB + i);
+ TTXI("UINameID", NAMEBASE_GSUB + featidx);
printf("</FeatureParamsStylisticSet>\n");
} else {
int nparam = 0;
while (nparam < MAXSUBNAME &&
- gsub_features[i].subnames[nparam])
+ feat->subnames[nparam])
nparam++;
printf("<FeatureParamsCharacterVariants>\n");
TTXI("Format", 0);
- TTXI("FeatUILabelNameID", NAMEBASE_GSUB + i);
+ TTXI("FeatUILabelNameID",
+ NAMEBASE_GSUB + featidx);
TTXI("FeatUITooltipTextNameID", 0);
TTXI("SampleTextNameID", 0);
TTXI("NumNamedParameters", nparam);
TTXI("FirstParamUILabelNameID",
- NAMEBASE_GSUB_SUB + MAXSUBNAME * i);
+ NAMEBASE_GSUB_SUB + MAXSUBNAME * featidx);
printf("</FeatureParamsCharacterVariants>\n");
}
}
/* We only have one GSUB lookup per feature, thankfully. */
- TTXI("LookupListIndex", i);
+ TTXI("LookupListIndex", featidx);
printf("</Feature>\n");
printf("</FeatureRecord>\n");
}