chiark / gitweb /
Construct 'ssXX' and 'cvXX' lookups using X macros
authorBen Harris <bjh21@bjh21.me.uk>
Tue, 14 Jan 2025 01:05:28 +0000 (01:05 +0000)
committerBen Harris <bjh21@bjh21.me.uk>
Tue, 14 Jan 2025 23:21:24 +0000 (23:21 +0000)
In general, we want each Stylistic Set to be constructed out of a
collection of Character Variants.  At the moment, this is fairly
simple, but if I start putting variants of more characters into these
features (for example, adding questiondown.open to go with
question.open), it will get awkward keeping them in sync.  But the two
kinds of lookup want different XML, so they can't just be copied
as-is.

One approach would be to have a C data structure that gets used to
generate both sets of lookups, but an alternative is to extend the
existing pre-processor magic to use X macros to construct the two
lookups.  This is what I've done.

At the moment, this is just using the existing macros that generate
XML, but driving them from another set of macros, one for each
Character Variant feature.  The Stylistic Sets then invoke all the
macros for the Character Variants they include.

There are a couple of open problems.  One is the (single, so far) case
where there are two variants of a character, namely 'D'.  This should
be dealt with by paramaterising the variant macro, but I've not got
around to that yet.  The other is that the macro names are largely
horrible.

bedstead.c

index bbae63d0a9a6a7d570dc6f8fde563619f8645551..37a31202d819186b1a3768a3eadbe14b4a4f23d0 100644 (file)
@@ -2723,6 +2723,24 @@ static struct alt_sub_override {
        { "ugrave", { "ugrave.roundjoined", "ugrave.sc" } },
 };
 
+/*
+ * Define all the Character Variant features using X macros.  These
+ * are then used to create 'cvXX' features and grouped into 'ssXX'
+ * features.
+ */
+#define CV12 VAR2("comma", ".left")
+#define CV14 VAR2("period", ".large")
+#define CV26 VAR2("colon", ".leftsmall")
+#define CV27 VAR2("semicolon", ".left")
+#define CV31 VAR2("question", ".open")
+#define CV42 VAR2("J", ".narrow")
+#define CV44 VAR2("L", ".narrow")
+#define CV61 VAR2("ugrave",".roundjoined")
+#define CV74 VAR2("j", ".serif")
+#define CV79 VAR2("ocircumflex", ".large")
+#define CV84 VAR2("t", ".small")
+#define CV96 VAR2("ccedilla", ".angular")
+
 static struct gsub_feature {
        char const *tag;
 #define SCRIPT_DFLT 0x01
@@ -2742,24 +2760,15 @@ static struct gsub_feature {
        { "rtlm", SCRIPT_ALL, .suffix = ".rtlm" },
 #define SINGLESUB(in, out) "<Substitution in='" in "' out='" out "'/>\n"
 #define SUFFIXSUB(base, suffix) SINGLESUB(base, base suffix)
+#define VAR2 SUFFIXSUB
        { "ss01", SCRIPT_ALL, .name = "SAA5051",
-         .xml = "<SingleSubst>\n" SUFFIXSUB("comma", ".left")
-         SUFFIXSUB("period", ".large") SUFFIXSUB("colon", ".leftsmall")
-         SUFFIXSUB("semicolon", ".left") SUFFIXSUB("question", ".open")
-         SUFFIXSUB("D", ".serif") SUFFIXSUB("J", ".narrow")
-         SUFFIXSUB("L", ".narrow") SUFFIXSUB("j", ".serif")
-         SUFFIXSUB("t", ".small") "</SingleSubst>\n" },
+         .xml = "<SingleSubst>\n" CV12 CV14 CV26 CV27 CV31
+         SUFFIXSUB("D", ".serif") CV42 CV44 CV74 CV84 "</SingleSubst>\n" },
        { "ss02", SCRIPT_ALL, .name = "SAA5052",
-         .xml = "<SingleSubst>\n" SUFFIXSUB("comma", ".left")
-         SUFFIXSUB("period", ".large") SUFFIXSUB("colon", ".leftsmall")
-         SUFFIXSUB("semicolon", ".left") SUFFIXSUB("question", ".open")
-         SUFFIXSUB("D", ".narrow") SUFFIXSUB("J", ".narrow")
-         SUFFIXSUB("L", ".narrow") SUFFIXSUB("j", ".serif")
-         SUFFIXSUB("t", ".small") "</SingleSubst>\n" },
+         .xml = "<SingleSubst>\n" CV12 CV14 CV26 CV27 CV31
+         SUFFIXSUB("D", ".narrow") CV42 CV44 CV74 CV84 "</SingleSubst>\n" },
        { "ss04", SCRIPT_ALL, .name = "SAA5054",
-         .xml = "<SingleSubst>\n" SUFFIXSUB("ugrave", ".roundjoined")
-         SUFFIXSUB("ocircumflex", ".large") SUFFIXSUB("ccedilla", ".angular")
-         "</SingleSubst>\n" },
+         .xml = "<SingleSubst>\n" CV61 CV79 CV96 "</SingleSubst>\n" },
 #define ALT1(g) "<Alternate glyph='" g "'/>"
 #define ALT2(a, b) ALT1(a) ALT1(b)
 #define ALT3(a, b, c) ALT1(a) ALT2(b, c)
@@ -2771,37 +2780,27 @@ static struct gsub_feature {
               ALTSET(b, ALT3(a, b, c))         \
               ALTSET(c, ALT3(a, b, c)))
 #define CV2(base, a) CROSSALT2(base, base a)
+#undef VAR2
+#define VAR2 CV2
 #define CV3(base, a, b) CROSSALT3(base, base a, base b)
        /*
         * Where possible, Character Variant features have numbers
         * that are 32 less than the ASCII code of the base character.
         */
-       { "cv12", SCRIPT_ALL, .name = "comma variants",
-         .xml = CV2("comma", ".left") },
-       { "cv14", SCRIPT_ALL, .name = "full-stop variants",
-         .xml = CV2("period", ".large") },
-       { "cv26", SCRIPT_ALL, .name = "colon variants",
-         .xml = CV2("colon", ".leftsmall") },
-       { "cv27", SCRIPT_ALL, .name = "semicolon variants",
-         .xml = CV2("semicolon", ".left") },
-       { "cv31", SCRIPT_ALL, .name = "question-mark variants",
-         .xml = CV2("question", ".open") },
+       { "cv12", SCRIPT_ALL, .name = "comma variants", .xml = CV12 },
+       { "cv14", SCRIPT_ALL, .name = "full-stop variants", .xml = CV14 },
+       { "cv26", SCRIPT_ALL, .name = "colon variants", .xml = CV26 },
+       { "cv27", SCRIPT_ALL, .name = "semicolon variants", .xml = CV27 },
+       { "cv31", SCRIPT_ALL, .name = "question-mark variants", .xml = CV31 },
        { "cv38", SCRIPT_ALL, .name = "capital-D variants",
          .xml = CV3("D", ".serif", ".narrow") },
-       { "cv42", SCRIPT_ALL, .name = "capital-J variants",
-         .xml = CV2("J", ".narrow") },
-       { "cv44", SCRIPT_ALL, .name = "capital-L variants",
-         .xml = CV2("L", ".narrow") },
-       { "cv61", SCRIPT_ALL, .name = "small-u-grave variants",
-         .xml = CV2("ugrave",".roundjoined") },
-       { "cv74", SCRIPT_ALL, .name = "small-j variants",
-         .xml = CV2("j", ".serif") },
-       { "cv79", SCRIPT_ALL, .name = "small-o variants",
-         .xml = CV2("ocircumflex", ".large") },
-       { "cv84", SCRIPT_ALL, .name = "small-t variants",
-         .xml = CV2("t", ".small") },
-       { "cv96", SCRIPT_ALL, .name = "cedilla variants",
-         .xml = CV2("ccedilla", ".angular") },
+       { "cv42", SCRIPT_ALL, .name = "capital-J variants", .xml = CV42 },
+       { "cv44", SCRIPT_ALL, .name = "capital-L variants", .xml = CV44 },
+       { "cv61", SCRIPT_ALL, .name = "small-u-grave variants", .xml = CV61 },
+       { "cv74", SCRIPT_ALL, .name = "small-j variants", .xml = CV74 },
+       { "cv79", SCRIPT_ALL, .name = "small-o variants", .xml = CV79 },
+       { "cv84", SCRIPT_ALL, .name = "small-t variants", .xml = CV84 },
+       { "cv96", SCRIPT_ALL, .name = "cedilla variants", .xml = CV96 },
        { "ss14", SCRIPT_ALL,  ".sep4", .name = "4-cell separated graphics" },
        { "ss16", SCRIPT_ALL,  ".sep6", .name = "6-cell separated graphics" },
 };