summaryrefslogtreecommitdiff
path: root/src/features
diff options
context:
space:
mode:
authorRasmus Andersson <rasmus@notion.se>2019-08-05 01:17:39 +0300
committerRasmus Andersson <rasmus@notion.se>2019-08-05 01:17:39 +0300
commit49cd0c56c80c87ed721a3a317e891348f4515da1 (patch)
tree704f971fd494073e67c8e1e518af8f5aa32ea5cb /src/features
parent3c2b3619da463f2f86a4a654495efb4e4fda504d (diff)
downloadinter-49cd0c56c80c87ed721a3a317e891348f4515da1.tar.xz
moves feature code out of the glyphs file
Diffstat (limited to 'src/features')
-rw-r--r--src/features/README.md21
-rw-r--r--src/features/calt.fea237
-rw-r--r--src/features/ccmp.fea556
-rw-r--r--src/features/cpsp.fea1
-rw-r--r--src/features/cv01-one.fea5
-rw-r--r--src/features/cv02-four.fea5
-rw-r--r--src/features/cv03-six.fea5
-rw-r--r--src/features/cv04-nine.fea5
-rw-r--r--src/features/cv05-l-tail.fea14
-rw-r--r--src/features/cv06-r.fea14
-rw-r--r--src/features/cv07-germandbls.fea2
-rw-r--r--src/features/cv08-i-serif.fea33
-rw-r--r--src/features/cv09-three.fea5
-rw-r--r--src/features/cv10-g-spur.fea11
-rw-r--r--src/features/cv11-single-storey-a.fea33
-rw-r--r--src/features/dlig.fea4
-rw-r--r--src/features/frac.fea198
-rw-r--r--src/features/liga.fea282
-rw-r--r--src/features/salt.fea81
-rw-r--r--src/features/ss01-alt-digits.fea21
-rw-r--r--src/features/ss02-disambiguation.fea51
-rw-r--r--src/features/ss03-r-curve.fea332
-rw-r--r--src/features/subs.fea43
-rw-r--r--src/features/sups.fea43
-rw-r--r--src/features/zero.fea4
25 files changed, 2006 insertions, 0 deletions
diff --git a/src/features/README.md b/src/features/README.md
new file mode 100644
index 000000000..75c85a84f
--- /dev/null
+++ b/src/features/README.md
@@ -0,0 +1,21 @@
+# OpenType features
+
+This directory contains most (but not all) OpenType feature code.
+
+- Some features are maintained by the Glyphs application and are stored in the .glyphs file.
+- The order of features are defined in the .glyphs file
+
+Each feature file in this directory is automatically wrapped in a `feature {...}` block.
+For example, `cv07.fea` contains the following code:
+
+```fea
+sub germandbls by germandbls.1;
+```
+
+And when the font is compiled, it actually becomes:
+
+```
+feature cv07 {
+ sub germandbls by germandbls.1;
+}
+```
diff --git a/src/features/calt.fea b/src/features/calt.fea
new file mode 100644
index 000000000..8b1ad6dc4
--- /dev/null
+++ b/src/features/calt.fea
@@ -0,0 +1,237 @@
+# cap-height tall glyphs
+@UC = [
+ @Uppercase
+ @Numeral
+
+ # punctuation
+ ampersand exclam exclamdbl exclamdown uni2049 question uni2047 uni2048
+ questiondown interrobang invertedinterrobang bar paragraph
+
+ # currency
+ dollar cent yen sterling florin uni20BA uni20BD euro uni20B9 tenge peseta
+ peso kip won lira austral hryvnia naira guarani coloncurrency cedi cruzeiro
+ tugrik uni20AF mill afii57636 manat rupee lari franc
+
+ # cap-tall symbols
+ numero triagrt triagdn triagup warningSign blackleftpointingtriangle
+ circleblack circlewhite
+ diamondblack diamondblack_x diamondwhite diamondwhite_x
+ sunWithRays blackSunWithRays
+ heartWhiteSuit heartBlackSuit heavyBlackHeart
+ upBlackArrow upWhiteArrow
+ capslock placeofinterestsign control projective option alternativekeysymbol
+ brokenCircleNorthWestArrow anticlockwiseOpenCircleArrow
+ clockwiseOpenCircleArrow
+ deleteleft deleteright clear ejectsymbol
+
+ # percent and fractions
+ onehalf onethird onequarter threequarters fivesixths onefraction seveneighths
+ oneeighth fiveeighths threeeighths percent perthousand pertenthousand uni214D
+ cadauna careof accountof addresssubject
+];
+
+# x-height tall glyphs
+@LC = [
+ @Lowercase
+];
+
+@CASE_DELIM_L = [
+ braceleft braceright
+ bracketleft bracketright
+ parenleft parenright
+];
+@CASE_NONDELIM_L = [
+ at
+ multiply
+ minus
+ plus
+ plusminus
+ divide
+ equal
+ notequal
+ endash
+ figuredash
+ emdash
+ hyphen
+ bullet
+ openbullet
+ hyphenbullet
+ trianglebullet
+ blackleftbullet
+ blackrightbullet
+ leftArrow
+ leftLongArrow
+ leftLongArrow2
+ rightArrow
+ rightLongArrow
+ rightLongArrow2
+ leftRightArrow
+ leftRightLongArrow
+ colon
+ approxequal
+ asciitilde
+ less
+ greater
+ lessequal
+ greaterequal
+];
+@CASE_L = [
+ @CASE_DELIM_L
+ @CASE_NONDELIM_L
+];
+
+@CASE_DELIM_R = [
+ braceleft.case braceright.case
+ bracketleft.case bracketright.case
+ parenleft.case parenright.case
+];
+@CASE_NONDELIM_R = [
+ at.case
+ multiply.case
+ minus.case
+ plus.case
+ plusminus.case
+ divide.case
+ equal.case
+ notequal.case
+ endash.case
+ figuredash.case
+ emdash.case
+ hyphen.case
+ bullet.case
+ openbullet.case
+ hyphenbullet.case
+ trianglebullet.case
+ blackleftbullet.case
+ blackrightbullet.case
+ leftArrow.case
+ leftLongArrow.case
+ leftLongArrow2.case
+ rightArrow.case
+ rightLongArrow.case
+ rightLongArrow2.case
+ leftRightArrow.case
+ leftRightLongArrow.case
+ colon.case
+ approxequal.case
+ asciitilde.case
+ less.case
+ greater.case
+ lessequal.case
+ greaterequal.case
+];
+@CASE_R = [
+ @CASE_DELIM_R
+ @CASE_NONDELIM_R
+];
+
+@DASH = [
+ hyphen hyphen.case
+ endash endash.case
+ emdash emdash.case
+ minus minus.case
+];
+
+# ---------------------------------------------------
+
+# :-)
+sub colon' @DASH [parenright parenright.case] by colon.case;
+sub [colon colon.case] hyphen' [parenright parenright.case] by hyphen.case;
+sub [colon colon.case] endash' [parenright parenright.case] by endash.case;
+sub [colon colon.case] emdash' [parenright parenright.case] by emdash.case;
+sub [colon colon.case] @DASH parenright' by parenright.case;
+
+# A foo' -> A foo.case
+#
+# ignore subs adjacent to lower case
+#
+# x[]X
+ignore sub @LC @CASE_DELIM_L @CASE_DELIM_L @UC;
+ignore sub @LC @CASE_DELIM_L @UC;
+ignore sub @LC @CASE_DELIM_L @Whitespace @UC;
+ignore sub @LC @CASE_DELIM_L @Whitespace @Whitespace @UC;
+#
+# short runs of uc-lc, e.g "(Xx)", "[Zzz]"
+ignore sub @CASE_DELIM_L @UC @LC @CASE_DELIM_L;
+ignore sub @CASE_DELIM_L @UC @All @LC @CASE_DELIM_L;
+#
+# e.g. "x-"
+# TODO: figure out how to ignore "x--A"
+ignore sub @LC @CASE_L;
+#
+# e.g. "-x", "--x", "---x", "----x", "-----x"
+ignore sub @CASE_L @LC;
+ignore sub @CASE_L @CASE_L @LC;
+ignore sub @CASE_L @CASE_L @CASE_L @LC;
+ignore sub @CASE_L @CASE_L @CASE_L @CASE_L @LC;
+ignore sub @CASE_L @CASE_L @CASE_L @CASE_L @CASE_L @LC;
+#
+# pairs with space, e.g. "( ) M" since we don't support subbing
+# all on the left side.
+ignore sub @CASE_DELIM_L @Whitespace @CASE_DELIM_L @Whitespace [ @UC @CASE_R ];
+ignore sub @CASE_DELIM_L @CASE_DELIM_L @Whitespace [ @UC @CASE_R ];
+#
+# e.g. "A-", "A -", "A -"
+sub [ @UC @CASE_R ] @CASE_L' by @CASE_R;
+sub [ @UC @CASE_R ] @Whitespace @CASE_L' by @CASE_R;
+sub [ @UC @CASE_R ] @Whitespace @Whitespace @CASE_L' by @CASE_R;
+
+# foo' foo foo foo foo A -> foo.case foo foo foo foo A
+# foo' foo foo foo A -> foo.case foo foo foo A
+# foo' foo foo A -> foo.case foo foo A
+# foo' foo A -> foo.case foo A
+# foo' A -> foo.case A
+# Note: since we look quite far back, sequences like x{}[]M will case both
+# the square brackets next to M _and_ the curly braces to become .case
+#
+# e.g. "-A", "--A", "---A", "----A", "-----A"
+sub @CASE_L' [ @UC @CASE_R ] by @CASE_R;
+sub @CASE_L' @CASE_L [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L [ @CASE_R @UC ] by @CASE_R;
+#
+# e.g. "- A", "-- A", "--- A", "---- A", "----- A"
+sub @CASE_L' @Whitespace [ @UC @CASE_R ] by @CASE_R;
+sub @CASE_L' @CASE_L @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L @Whitespace [ @CASE_R @UC ] by @CASE_R;
+#
+# e.g. "- A", "-- A", "--- A", "---- A", "----- A"
+sub @CASE_L' @Whitespace @Whitespace [ @UC @CASE_R ] by @CASE_R;
+sub @CASE_L' @CASE_L @Whitespace @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @Whitespace @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L @Whitespace @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @CASE_L @CASE_L @CASE_L @CASE_L @Whitespace @Whitespace [ @CASE_R @UC ] by @CASE_R;
+sub @CASE_L' @Whitespace @Whitespace @Whitespace [ @UC @CASE_R ] by @CASE_R; # e.g. "- A"
+
+# X(_)
+@Punctuation = [
+ slash bar quoteleft quoteright apostrophemod quotesingle quotedbl
+ quotedblleft quotedblright quotedblbase quotesinglbase prime doubleprime
+ tripleprime quadrupleprime primerev doubleprimerev tripleprimerev primemod
+ doubleprimemod comma period ellipsis twodotleader semicolon underscore
+ asciicircum circumflex
+ asterisk
+];
+sub @CASE_DELIM_R @Punctuation @CASE_DELIM_L' by @CASE_DELIM_R;
+
+# in between number position adjustment, e.g. 3x4 -> 3×4
+@between_num_L = [
+ multiply
+ asterisk
+];
+@between_num_R = [
+ multiply.case
+ asterisk.case
+];
+sub @Numeral @between_num_L' @Numeral by @between_num_R; # 3*9
+sub @Numeral @Whitespace @between_num_L' @Numeral by @between_num_R; # 3 *9
+sub @Numeral @Whitespace @Whitespace @between_num_L' @Numeral by @between_num_R; # 3 *9
+sub @Numeral @between_num_L' @Whitespace @Numeral by @between_num_R; # 3* 9
+sub @Numeral @Whitespace @between_num_L' @Whitespace @Numeral by @between_num_R; # 3 * 9
+sub @Numeral @Whitespace @Whitespace @between_num_L' @Whitespace @Numeral by @between_num_R; # 3 * 9
+sub @Numeral @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3* 9
+sub @Numeral @Whitespace @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3 * 9
+sub @Numeral @Whitespace @Whitespace @between_num_L' @Whitespace @Whitespace @Numeral by @between_num_R; # 3 * 9
diff --git a/src/features/ccmp.fea b/src/features/ccmp.fea
new file mode 100644
index 000000000..20dbb8d41
--- /dev/null
+++ b/src/features/ccmp.fea
@@ -0,0 +1,556 @@
+@CCMP_ACC = [
+ gravecomb acutecomb tildecomb brevetildecomb.cn brevehookcomb.cn
+ breveacutecomb.cn circumflextildecomb.cn circumflexhookcomb.cn
+ circumflexgravecomb.cn circumflexacutecomb.cn brevegravecomb.cn
+ macroncomb dieresismacroncomb.cn dieresisacutecomb.cn
+ dieresiscaroncomb.cn dieresisgravecomb.cn dotmacroncomb.cn
+ tildeacutecomb macrongravecomb.cn macronacutecomb.cn
+ macrondieresiscomb.cn acutedotcomb.cn carondotcomb.cn
+ tildemacroncomb.cn tildedieresiscomb.cn circumflexnosp overscorenosp
+ brevenosp dotnosp dieresisnosp hook ringnosp acutedblnosp caroncmb
+ linevertnosp linevertdblnosp dblgravecmb candrabindunosp breveinvnosp
+ commaturnsupnosp commaabovecmb commasuprevnosp commaaboverightcmb
+ anglesupnosp hornnosp xsupnosp tildevertsupnosp overscoredblnosp
+ graveleftnosp acuterightnosp perispomenigreekcmb koroniscmb
+ diaeresistonosnosp uni0346 uni034A uni034B uni034C arrowheadrightabovecomb uni0351
+ uni0352 uni0357 uni0358 uni035B uni1DC0 uni1DC1 uni1DC3 uni1DC4
+ uni1DC5 uni1DC6 uni1DC7 uni1DC8 uni1DC9 uni1DCB uni1DCC uni1DCD
+ uni1DCE uni1DD1 uni1DD2 uni1DD3 uni1DD4 uni1DD5 uni1DD6 uni1DD7
+ uni1DD8 uni1DD9 uni1DDA uni1DDB uni1DDC uni1DDD uni1DDE uni1DDF
+ uni1DE0 uni1DE1 uni1DE2 uni1DE3 uni1DE4 uni1DE5 uni1DE6 uni1DE7
+ uni1DE8 uni1DE9 uni1DEA uni1DEB uni1DEC uni1DED uni1DEE uni1DEF
+ uni1DF0 uni1DF1 uni1DF2 uni1DF3 uni1DF4 uni1DF5 uni1DFE uni0363
+ uni0364 uni0365 uni0366 uni0367 uni0368 uni0369 uni036A uni036B
+ uni036C uni036D uni036E uni036F titlocyrilliccmb
+ palatalizationcyrilliccmb dasiapneumatacyrilliccmb
+ psilipneumatacyrilliccmb uni0487 uni20F0 uniA69F uni2DFF uni20DC
+ uniFE20 uniFE21 uniFE22 uniFE23 uniFE24 uniFE25 uniFE26
+];
+
+# Transpose sequences like /i /gravecomb -> /idotless /gravecomb
+lookup ccmp02 {
+ sub i' @CCMP_ACC by idotless;
+ sub j' @CCMP_ACC by jdotless;
+ sub ibar' @CCMP_ACC by uni0268.ccmp;
+ sub iogonek' @CCMP_ACC by uni012F.ccmp; # iogonek is generated
+ sub uni0249' @CCMP_ACC by uni0249.ccmp;
+ sub jcrosstail' @CCMP_ACC by jcrosstail.ccmp;
+ sub yotgreek' @CCMP_ACC by jdotless;
+ sub icyrillic' @CCMP_ACC by idotless;
+ sub jecyrillic' @CCMP_ACC by jdotless;
+ sub itildebelow' @CCMP_ACC by uni1E2D.ccmp; # uni1E2D.ccmp is generated
+ sub idotbelow' @CCMP_ACC by uni1ECB.ccmp; # both are generated
+ sub i.numr' @CCMP_ACC by uni2071.ccmp;
+} ccmp02;
+
+lookup ccmp03 {
+ sub d caroncmb by dcaron;
+ sub l caroncmb by lcaron;
+ sub t caroncmb by tcaron;
+
+ sub A gravecomb by Agrave;
+ sub A acutecomb by Aacute;
+ sub A circumflexnosp by Acircumflex;
+ sub A tildecomb by Atilde;
+ sub A dieresisnosp by Adieresis;
+ sub A ringnosp by Aring;
+ sub A ringacute.cn by Aringacute;
+ sub C cedillanosp by Ccedilla;
+ sub E gravecomb by Egrave;
+ sub E acutecomb by Eacute;
+ sub E circumflexnosp by Ecircumflex;
+ sub E dieresisnosp by Edieresis;
+ sub I gravecomb by Igrave;
+ sub I acutecomb by Iacute;
+ sub I circumflexnosp by Icircumflex;
+ sub I dieresisnosp by Idieresis;
+ sub N tildecomb by Ntilde;
+ sub O gravecomb by Ograve;
+ sub O acutecomb by Oacute;
+ sub O circumflexnosp by Ocircumflex;
+ sub O tildecomb by Otilde;
+ sub O dieresisnosp by Odieresis;
+ sub U gravecomb by Ugrave;
+ sub U acutecomb by Uacute;
+ sub U circumflexnosp by Ucircumflex;
+ sub U dieresisnosp by Udieresis;
+ sub Y acutecomb by Yacute;
+ sub a gravecomb by agrave;
+ sub a acutecomb by aacute;
+ sub a circumflexnosp by acircumflex;
+ sub a tildecomb by atilde;
+ sub a dieresisnosp by adieresis;
+ sub a ringnosp by aring;
+ sub a ringacute.cn by aringacute;
+ sub c cedillanosp by ccedilla;
+ sub e gravecomb by egrave;
+ sub e acutecomb by eacute;
+ sub e circumflexnosp by ecircumflex;
+ sub e dieresisnosp by edieresis;
+ sub idotless gravecomb by igrave;
+ sub idotless acutecomb by iacute;
+ sub idotless circumflexnosp by icircumflex;
+ sub idotless dieresisnosp by idieresis;
+ sub n tildecomb by ntilde;
+ sub o gravecomb by ograve;
+ sub o acutecomb by oacute;
+ sub o circumflexnosp by ocircumflex;
+ sub o tildecomb by otilde;
+ sub o dieresisnosp by odieresis;
+ sub u gravecomb by ugrave;
+ sub u acutecomb by uacute;
+ sub u circumflexnosp by ucircumflex;
+ sub u dieresisnosp by udieresis;
+ sub y acutecomb by yacute;
+ sub y dieresisnosp by ydieresis;
+ sub A macroncomb by Amacron;
+ sub a macroncomb by amacron;
+ sub A brevenosp by Abreve;
+ sub a brevenosp by abreve;
+ sub A ogoneknosp by Aogonek;
+ sub a ogoneknosp by aogonek;
+ sub C acutecomb by Cacute;
+ sub c acutecomb by cacute;
+ sub C circumflexnosp by Ccircumflex;
+ sub c circumflexnosp by ccircumflex;
+ sub C dotnosp by Cdotaccent;
+ sub c dotnosp by cdotaccent;
+ sub C caroncmb by Ccaron;
+ sub c caroncmb by ccaron;
+ sub D caroncmb by Dcaron;
+ sub E macroncomb by Emacron;
+ sub e macroncomb by emacron;
+ sub E brevenosp by Ebreve;
+ sub e brevenosp by ebreve;
+ sub E dotnosp by Edotaccent;
+ sub e dotnosp by edotaccent;
+ sub E ogoneknosp by Eogonek;
+ sub e ogoneknosp by eogonek;
+ sub E caroncmb by Ecaron;
+ sub e caroncmb by ecaron;
+ sub G circumflexnosp by Gcircumflex;
+ sub g circumflexnosp by gcircumflex;
+ sub G brevenosp by Gbreve;
+ sub g brevenosp by gbreve;
+ sub G dotnosp by Gdotaccent;
+ sub g dotnosp by gdotaccent;
+ sub G commaaccent by Gcommaaccent;
+ sub g commaaccentrotate.cn by gcommaaccent;
+ sub H circumflexnosp by Hcircumflex;
+ sub h circumflexnosp by hcircumflex;
+ sub I tildecomb by Itilde;
+ sub idotless tildecomb by itilde;
+ sub I macroncomb by Imacron;
+ sub idotless macroncomb by imacron;
+ sub I brevenosp by Ibreve;
+ sub idotless brevenosp by ibreve;
+ sub I ogoneknosp by Iogonek;
+ sub i ogoneknosp by iogonek;
+ sub I dotnosp by Idotaccent;
+ sub J circumflexnosp by Jcircumflex;
+ sub jdotless circumflexnosp by jcircumflex;
+ sub K commaaccent by Kcommaaccent;
+ sub k commaaccent by kcommaaccent;
+ sub L acutecomb by Lacute;
+ sub l acutecomb by lacute;
+ sub L commaaccent by Lcommaaccent;
+ sub l commaaccent by lcommaaccent;
+ sub L dotnosp by Ldot;
+ sub l dotnosp by ldot;
+ sub N acutecomb by Nacute;
+ sub n acutecomb by nacute;
+ sub N commaaccent by Ncommaaccent;
+ sub n commaaccent by ncommaaccent;
+ sub N caroncmb by Ncaron;
+ sub n caroncmb by ncaron;
+ sub O macroncomb by Omacron;
+ sub o macroncomb by omacron;
+ sub O brevenosp by Obreve;
+ sub o brevenosp by obreve;
+ sub O acutedblnosp by Ohungarumlaut;
+ sub o acutedblnosp by ohungarumlaut;
+ sub R acutecomb by Racute;
+ sub r acutecomb by racute;
+ sub R commaaccent by Rcommaaccent;
+ sub r commaaccent by rcommaaccent;
+ sub R caroncmb by Rcaron;
+ sub r caroncmb by rcaron;
+ sub S acutecomb by Sacute;
+ sub s acutecomb by sacute;
+ sub S circumflexnosp by Scircumflex;
+ sub s circumflexnosp by scircumflex;
+ sub S cedillanosp by Scedilla;
+ sub s cedillanosp by scedilla;
+ sub S commaaccent by Scommaaccent;
+ sub s commaaccent by scommaaccent;
+ sub S caroncmb by Scaron;
+ sub s caroncmb by scaron;
+ sub T commaaccent by uni021A;
+ sub t commaaccent by tcommaaccent;
+ sub T cedillanosp by Tcommaaccent;
+ sub t cedillanosp by tcedilla;
+ sub T caroncmb by Tcaron;
+ sub U tildecomb by Utilde;
+ sub u tildecomb by utilde;
+ sub U macroncomb by Umacron;
+ sub u macroncomb by umacron;
+ sub U brevenosp by Ubreve;
+ sub u brevenosp by ubreve;
+ sub U ringnosp by Uring;
+ sub u ringnosp by uring;
+ sub U acutedblnosp by Uhungarumlaut;
+ sub u acutedblnosp by uhungarumlaut;
+ sub U ogoneknosp by Uogonek;
+ sub u ogoneknosp by uogonek;
+ sub W circumflexnosp by Wcircumflex;
+ sub w circumflexnosp by wcircumflex;
+ sub Y circumflexnosp by Ycircumflex;
+ sub y circumflexnosp by ycircumflex;
+ sub Y dieresisnosp by Ydieresis;
+ sub Z acutecomb by Zacute;
+ sub z acutecomb by zacute;
+ sub Z dotnosp by Zdotaccent;
+ sub z dotnosp by zdotaccent;
+ sub Z caroncmb by Zcaron;
+ sub z caroncmb by zcaron;
+ sub AE acutecomb by AEacute;
+ sub ae acutecomb by aeacute;
+ sub Oslash acutecomb by Oslashacute;
+ sub oslash acutecomb by oslashacute;
+ #sub z caroncmb by zcaron;
+ sub W gravecomb by Wgrave;
+ sub w gravecomb by wgrave;
+ sub W acutecomb by Wacute;
+ sub w acutecomb by wacute;
+ sub W dieresisnosp by Wdieresis;
+ sub w dieresisnosp by wdieresis;
+ sub Y gravecomb by Ygrave;
+ sub y gravecomb by ygrave;
+ sub jdotless caroncmb by jcaron;
+ sub A dotbelow by Adotbelow;
+ sub a dotbelow by adotbelow;
+ sub A hook by Ahookabove;
+ sub a hook by ahookabove;
+ #sub A circumflexacutecomb.cn by uni1EA4;
+ sub A circumflexnosp acutecomb by Acircumflexacute;
+ sub a circumflexacutecomb.cn by acircumflexacute;
+ #sub A circumflexgravecomb.cn by uni1EA6;
+ sub A circumflexnosp gravecomb by Acircumflexgrave;
+ sub a circumflexgravecomb.cn by acircumflexgrave;
+ #sub A circumflexhookcomb.cn by uni1EA8;
+ sub A circumflexnosp hook by Acircumflexhookabove;
+ sub a circumflexhookcomb.cn by acircumflexhookabove;
+ #sub A circumflextildecomb.cn by uni1EAA;
+ sub A circumflexnosp tildecomb by Acircumflextilde;
+ sub a circumflextildecomb.cn by acircumflextilde;
+ #sub A breveacutecomb.cn by uni1EAE;
+ sub A brevenosp acutecomb by Abreveacute;
+ sub a breveacutecomb.cn by abreveacute;
+ #sub A brevegravecomb.cn by uni1EB0;
+ sub A brevenosp gravecomb by Abrevegrave;
+ sub a brevegravecomb.cn by abrevegrave;
+ #sub A brevehookcomb.cn by uni1EB2;
+ sub A brevenosp hook by Abrevehookabove;
+ sub a brevehookcomb.cn by abrevehookabove;
+ sub A brevetildecomb.cn by Abrevetilde;
+ sub a brevetildecomb.cn by abrevetilde;
+ sub E dotbelow by Edotbelow;
+ sub e dotbelow by edotbelow;
+ sub E hook by Ehookabove;
+ sub e hook by ehookabove;
+ sub E tildecomb by Etilde;
+ sub e tildecomb by etilde;
+ #sub E circumflexacutecomb.cn by uni1EBE;
+ sub E circumflexnosp acutecomb by Ecircumflexacute;
+ sub e circumflexacutecomb.cn by ecircumflexacute;
+ #sub E circumflexgravecomb.cn by uni1EC0;
+ sub E circumflexnosp gravecomb by Ecircumflexgrave;
+ sub e circumflexgravecomb.cn by ecircumflexgrave;
+ #sub E circumflexhookcomb.cn by uni1EC2;
+ sub E circumflexnosp hook by Ecircumflexhookabove;
+ sub e circumflexhookcomb.cn by ecircumflexhookabove;
+ #sub E circumflextildecomb.cn by uni1EC4;
+ sub E circumflexnosp tildecomb by Ecircumflextilde;
+ sub e circumflextildecomb.cn by ecircumflextilde;
+ sub I hook by Ihookabove;
+ sub idotless hook by ihookabove;
+ sub I dotbelow by Idotbelow;
+ sub i dotbelow by idotbelow;
+ sub O dotbelow by Odotbelow;
+ sub o dotbelow by odotbelow;
+ sub O hook by Ohookabove;
+ sub o hook by ohookabove;
+ #sub O circumflexacutecomb.cn by uni1ED0;
+ sub O circumflexnosp acutecomb by Ocircumflexacute;
+ sub o circumflexacutecomb.cn by ocircumflexacute;
+ #sub O circumflexgravecomb.cn by uni1ED2;
+ sub O circumflexnosp gravecomb by Ocircumflexgrave;
+ sub o circumflexgravecomb.cn by ocircumflexgrave;
+ #sub O circumflexhookcomb.cn by uni1ED4;
+ sub O circumflexnosp hook by Ocircumflexhookabove;
+ sub o circumflexhookcomb.cn by ocircumflexhookabove;
+ #sub O circumflextildecomb.cn by uni1ED6;
+ sub O circumflexnosp tildecomb by Ocircumflextilde;
+ sub o circumflextildecomb.cn by ocircumflextilde;
+ sub Ohorn acutecomb by Ohornacute;
+ sub ohorn acutecomb by ohornacute;
+ sub Ohorn gravecomb by Ohorngrave;
+ sub ohorn gravecomb by ohorngrave;
+ sub Ohorn hook by Ohornhookabove;
+ sub ohorn hook by ohornhookabove;
+ sub Ohorn tildecomb by Ohorntilde;
+ sub ohorn tildecomb by ohorntilde;
+ sub Ohorn dotbelow by Ohorndotbelow;
+ sub ohorn dotbelow by ohorndotbelow;
+ sub U dotbelow by Udotbelow;
+ sub u dotbelow by udotbelow;
+ sub U hook by Uhookabove;
+ sub u hook by uhookabove;
+ sub Uhorn acutecomb by Uhornacute;
+ sub uhorn acutecomb by uhornacute;
+ sub Uhorn gravecomb by Uhorngrave;
+ sub uhorn gravecomb by uhorngrave;
+ sub Uhorn hook by Uhornhookabove;
+ sub uhorn hook by uhornhookabove;
+ sub Uhorn tildecomb by Uhorntilde;
+ sub uhorn tildecomb by uhorntilde;
+ sub Uhorn dotbelow by Uhorndotbelow;
+ sub uhorn dotbelow by uhorndotbelow;
+ sub Y dotbelow by Ydotbelow;
+ sub y dotbelow by ydotbelow;
+ sub Y hook by Yhookabove;
+ sub y hook by yhookabove;
+ sub Y tildecomb by Ytilde;
+ sub y tildecomb by ytilde;
+ sub A caroncmb by Acaron;
+ sub a caroncmb by acaron;
+ sub I caroncmb by Icaron;
+ sub idotless caroncmb by icaron;
+ sub O caroncmb by Ocaron;
+ sub o caroncmb by ocaron;
+ sub U caroncmb by Ucaron;
+ sub u caroncmb by ucaron;
+ #sub U dieresismacroncomb.cn by uni01D5;
+ sub U dieresisnosp macroncomb by Udieresismacron;
+ sub u dieresismacroncomb.cn by udieresismacron;
+ #sub U dieresisacutecomb.cn by uni01D7;
+ sub U dieresisnosp acutecomb by Udieresisacute;
+ sub u dieresisacutecomb.cn by udieresisacute;
+ #sub U dieresiscaroncomb.cn by uni01D9;
+ sub U dieresisnosp caroncmb by Udieresiscaron;
+ sub u dieresiscaroncomb.cn by udieresiscaron;
+ #sub U dieresisgravecomb.cn by uni01DB;
+ sub U dieresisnosp gravecomb by Udieresisgrave;
+ sub u dieresisgravecomb.cn by udieresisgrave;
+ #sub A dieresismacroncomb.cn by uni01DE;
+ sub A dieresisnosp macroncomb by Adieresismacron;
+ sub a dieresismacroncomb.cn by adieresismacron;
+ #sub A dotmacroncomb.cn by uni01E0;
+ sub A dotnosp macroncomb by Adotmacron;
+ sub a dotmacroncomb.cn by adotmacron;
+ sub AE macroncomb by AEmacron;
+ sub ae macroncomb by aemacron;
+ sub G caroncmb by Gcaron;
+ sub g caroncmb by gcaron;
+ sub K caroncmb by Kcaron;
+ sub k caroncmb by kcaron;
+ sub O ogoneknosp by Oogonek;
+ sub o ogoneknosp by oogonek;
+ sub G acutecomb by Gacute;
+ sub g acutecomb by gacute;
+ sub N gravecomb by uni01F8;
+ sub n gravecomb by uni01F9;
+ sub A dblgravecmb by Adblgrave;
+ sub a dblgravecmb by adblgrave;
+ sub A breveinvnosp by Ainvertedbreve;
+ sub a breveinvnosp by ainvertedbreve;
+ sub E dblgravecmb by Edblgrave;
+ sub e dblgravecmb by edblgrave;
+ sub E breveinvnosp by Einvertedbreve;
+ sub e breveinvnosp by einvertedbreve;
+ sub I dblgravecmb by Idblgrave;
+ sub idotless dblgravecmb by idblgrave;
+ sub I breveinvnosp by Iinvertedbreve;
+ sub idotless breveinvnosp by iinvertedbreve;
+ sub O dblgravecmb by Odblgrave;
+ sub o dblgravecmb by odblgrave;
+ sub O breveinvnosp by Oinvertedbreve;
+ sub o breveinvnosp by oinvertedbreve;
+ sub R dblgravecmb by Rdblgrave;
+ sub r dblgravecmb by rdblgrave;
+ sub R breveinvnosp by Rinvertedbreve;
+ sub r breveinvnosp by rinvertedbreve;
+ sub U dblgravecmb by Udblgrave;
+ sub u dblgravecmb by udblgrave;
+ sub U breveinvnosp by Uinvertedbreve;
+ sub u breveinvnosp by uinvertedbreve;
+ sub H caroncmb by uni021E;
+ sub h caroncmb by uni021F;
+ sub A dotnosp by uni0226;
+ sub a dotnosp by uni0227;
+ sub E cedillanosp by uni0228;
+ sub e cedillanosp by uni0229;
+ #sub O dieresismacroncomb.cn by uni022A;
+ sub O dieresisnosp macroncomb by uni022A;
+ sub o dieresismacroncomb.cn by uni022B;
+ #sub O tildemacroncomb.cn by uni022C;
+ sub O tildecomb macroncomb by uni022C;
+ sub o tildemacroncomb.cn by uni022D;
+ sub O dotnosp by uni022E;
+ sub o dotnosp by uni022F;
+ #sub O dotmacroncomb.cn by uni0230;
+ sub O dotnosp macroncomb by uni0230;
+ sub o dotmacroncomb.cn by uni0231;
+ sub Y macroncomb by uni0232;
+ sub y macroncomb by uni0233;
+ sub Upsilonhooksymbol acutecomb by Upsilonacutehooksymbolgreek;
+ sub Upsilonhooksymbol dieresisnosp by Upsilondieresishooksymbolgreek;
+ sub B dotnosp by Bdotaccent;
+ sub b dotnosp by bdotaccent;
+ sub B dotbelow by Bdotbelow;
+ sub b dotbelow by bdotbelow;
+ sub B macronsubnosp by Blinebelow;
+ sub b macronsubnosp by blinebelow;
+ sub D dotnosp by Ddotaccent;
+ sub d dotnosp by ddotaccent;
+ sub D dotbelow by Ddotbelow;
+ sub d dotbelow by ddotbelow;
+ sub D macronsubnosp by Dlinebelow;
+ sub d macronsubnosp by dlinebelow;
+ sub D commaaccent by Dcedilla;
+ sub d commaaccent by dcedilla;
+ sub D circumflexsubnosp by Dcircumflexbelow;
+ sub d circumflexsubnosp by dcircumflexbelow;
+ #sub E macrongravecomb.cn by uni1E14;
+ sub E macroncomb gravecomb by Emacrongrave;
+ sub e macrongravecomb.cn by emacrongrave;
+ #sub E macronacutecomb.cn by uni1E16;
+ sub E macroncomb acutecomb by Emacronacute;
+ sub e macronacutecomb.cn by emacronacute;
+ sub E circumflexsubnosp by Ecircumflexbelow;
+ sub e circumflexsubnosp by ecircumflexbelow;
+ sub E tildesubnosp by Etildebelow;
+ sub e tildesubnosp by etildebelow;
+ sub F dotnosp by Fdotaccent;
+ sub f dotnosp by fdotaccent;
+ sub G macroncomb by Gmacron;
+ sub g macroncomb by gmacron;
+ sub H dotnosp by Hdotaccent;
+ sub h dotnosp by hdotaccent;
+ sub H dotbelow by Hdotbelow;
+ sub h dotbelow by hdotbelow;
+ sub H dieresisnosp by Hdieresis;
+ sub h dieresisnosp by hdieresis;
+ sub H brevesubnosp by Hbrevebelow;
+ sub h brevesubnosp by hbrevebelow;
+ sub I tildesubnosp by Itildebelow;
+ sub i tildesubnosp by itildebelow;
+ #sub I dieresisacutecomb.cn by Idieresisacute;
+ sub I dieresisnosp acutecomb by Idieresisacute;
+ sub idotless dieresisacutecomb.cn by idieresisacute;
+ sub K acutecomb by Kacute;
+ sub k acutecomb by kacute;
+ sub K dotbelow by Kdotbelow;
+ sub k dotbelow by kdotbelow;
+ sub K macronsubnosp by Klinebelow;
+ sub k macronsubnosp by klinebelow;
+ sub L dotbelow by Ldotbelow;
+ sub l dotbelow by ldotbelow;
+ sub L macronsubnosp by Llinebelow;
+ sub l macronsubnosp by llinebelow;
+ sub L circumflexsubnosp by Lcircumflexbelow;
+ sub l circumflexsubnosp by lcircumflexbelow;
+ sub M acutecomb by Macute;
+ sub m acutecomb by macute;
+ sub M dotnosp by Mdotaccent;
+ sub m dotnosp by mdotaccent;
+ sub M dotbelow by Mdotbelow;
+ sub m dotbelow by mdotbelow;
+ sub N dotnosp by Ndotaccent;
+ sub n dotnosp by ndotaccent;
+ sub N dotbelow by Ndotbelow;
+ sub n dotbelow by ndotbelow;
+ sub N macronsubnosp by Nlinebelow;
+ sub n macronsubnosp by nlinebelow;
+ sub N circumflexsubnosp by Ncircumflexbelow;
+ sub n circumflexsubnosp by ncircumflexbelow;
+ #sub O tildeacutecomb.cn by uni1E4C;
+ sub O tildecomb acutecomb by Otildeacute;
+ sub o tildeacutecomb by otildeacute;
+ #sub O tildedieresiscomb.cn by uni1E4E;
+ sub O tildecomb dieresisnosp by Otildedieresis;
+ sub o tildedieresiscomb.cn by otildedieresis;
+ #sub O macrongravecomb.cn by uni1E50;
+ sub O macroncomb gravecomb by Omacrongrave;
+ sub o macrongravecomb.cn by omacrongrave;
+ #sub O macronacutecomb.cn by uni1E52;
+ sub O macroncomb acutecomb by Omacronacute;
+ sub o macronacutecomb.cn by omacronacute;
+ sub P acutecomb by Pacute;
+ sub p acutecomb by pacute;
+ sub P dotnosp by Pdotaccent;
+ sub p dotnosp by pdotaccent;
+ sub R dotnosp by Rdotaccent;
+ sub r dotnosp by rdotaccent;
+ sub R dotbelow by Rdotbelow;
+ sub r dotbelow by rdotbelow;
+ sub R macronsubnosp by Rlinebelow;
+ sub r macronsubnosp by rlinebelow;
+ sub S dotnosp by Sdotaccent;
+ sub s dotnosp by sdotaccent;
+ sub S dotbelow by Sdotbelow;
+ sub s dotbelow by sdotbelow;
+ #sub S acutedotcomb.cn by uni1E64;
+ sub S acutecomb dotnosp by Sacutedotaccent;
+ sub s acutedotcomb.cn by sacutedotaccent;
+ #sub S carondotcomb.cn by uni1E66;
+ sub S caroncmb dotnosp by Scarondotaccent;
+ sub s carondotcomb.cn by scarondotaccent;
+ sub T dotnosp by Tdotaccent;
+ sub t dotnosp by tdotaccent;
+ sub T dotbelow by Tdotbelow;
+ sub t dotbelow by tdotbelow;
+ sub T macronsubnosp by Tlinebelow;
+ sub t macronsubnosp by tlinebelow;
+ sub T circumflexsubnosp by Tcircumflexbelow;
+ sub t circumflexsubnosp by tcircumflexbelow;
+ sub U dotdblsubnosp by Udieresisbelow;
+ sub u dotdblsubnosp by udieresisbelow;
+ sub U tildesubnosp by Utildebelow;
+ sub u tildesubnosp by utildebelow;
+ sub U circumflexsubnosp by Ucircumflexbelow;
+ sub u circumflexsubnosp by ucircumflexbelow;
+ #sub U tildeacutecomb.cn by uni1E78;
+ sub U tildecomb acutecomb by Utildeacute;
+ sub u tildeacutecomb by utildeacute;
+ #sub U macrondieresiscomb.cn by uni1E7A;
+ sub U macroncomb dieresisnosp by Umacrondieresis;
+ sub u macrondieresiscomb.cn by umacrondieresis;
+ sub V tildecomb by Vtilde;
+ sub v tildecomb by vtilde;
+ sub V dotbelow by Vdotbelow;
+ sub v dotbelow by vdotbelow;
+ sub W dotnosp by Wdotaccent;
+ sub w dotnosp by wdotaccent;
+ sub W dotbelow by Wdotbelow;
+ sub w dotbelow by wdotbelow;
+ sub X dotnosp by Xdotaccent;
+ sub x dotnosp by xdotaccent;
+ sub X dieresisnosp by Xdieresis;
+ sub x dieresisnosp by xdieresis;
+ sub Y dotnosp by Ydotaccent;
+ sub y dotnosp by ydotaccent;
+ sub Z circumflexnosp by Zcircumflex;
+ sub z circumflexnosp by zcircumflex;
+ sub Z dotbelow by Zdotbelow;
+ sub z dotbelow by zdotbelow;
+ sub Z macronsubnosp by Zlinebelow;
+ sub z macronsubnosp by zlinebelow;
+ sub h macronsubnosp by hlinebelow;
+ sub t dieresisnosp by tdieresis;
+ sub w ringnosp by wring;
+ sub y ringnosp by yring;
+ sub longs dotnosp by slongdotaccent;
+ sub A ringsubnosp by Aringbelow;
+ sub a ringsubnosp by aringbelow;
+} ccmp03;
diff --git a/src/features/cpsp.fea b/src/features/cpsp.fea
new file mode 100644
index 000000000..588933627
--- /dev/null
+++ b/src/features/cpsp.fea
@@ -0,0 +1 @@
+pos @Uppercase <16 0 32 0>;
diff --git a/src/features/cv01-one.fea b/src/features/cv01-one.fea
new file mode 100644
index 000000000..860915d97
--- /dev/null
+++ b/src/features/cv01-one.fea
@@ -0,0 +1,5 @@
+cvParameters { FeatUILabelNameID { name "Alternate one"; }; };
+sub one by one.ss01;
+sub one.tf by one.tf.ss01;
+sub one.squared by one.ss01.squared;
+sub one.circled by one.ss01.circled;
diff --git a/src/features/cv02-four.fea b/src/features/cv02-four.fea
new file mode 100644
index 000000000..6e2b3bd71
--- /dev/null
+++ b/src/features/cv02-four.fea
@@ -0,0 +1,5 @@
+cvParameters { FeatUILabelNameID { name "Open four"; }; };
+sub four by four.ss01;
+sub four.tf by four.tf.ss01;
+sub four.squared by four.ss01.squared;
+sub four.circled by four.ss01.circled;
diff --git a/src/features/cv03-six.fea b/src/features/cv03-six.fea
new file mode 100644
index 000000000..1e26b2e2e
--- /dev/null
+++ b/src/features/cv03-six.fea
@@ -0,0 +1,5 @@
+cvParameters { FeatUILabelNameID { name "Open six"; }; };
+sub six by six.ss01;
+sub six.tf by six.tf.ss01;
+sub six.squared by six.ss01.squared;
+sub six.circled by six.ss01.circled;
diff --git a/src/features/cv04-nine.fea b/src/features/cv04-nine.fea
new file mode 100644
index 000000000..f24b3352e
--- /dev/null
+++ b/src/features/cv04-nine.fea
@@ -0,0 +1,5 @@
+cvParameters { FeatUILabelNameID { name "Open nine"; }; };
+sub nine by nine.ss01;
+sub nine.tf by nine.tf.ss01;
+sub nine.squared by nine.ss01.squared;
+sub nine.circled by nine.ss01.circled;
diff --git a/src/features/cv05-l-tail.fea b/src/features/cv05-l-tail.fea
new file mode 100644
index 000000000..38da8fcdd
--- /dev/null
+++ b/src/features/cv05-l-tail.fea
@@ -0,0 +1,14 @@
+cvParameters { FeatUILabelNameID { name "Lower-case L with tail"; }; };
+sub l by l.ss02;
+sub lslash by lslash.ss02;
+sub lbar by lbar.ss02;
+sub lmidtilde by lmidtilde.ss02;
+sub lbelt by lbelt.ss02;
+sub ldot by ldot.ss02;
+sub lacute by lacute.ss02;
+sub lcommaaccent by lcommaaccent.ss02;
+sub lcaron by lcaron.ss02;
+sub ldotbelow by ldotbelow.ss02;
+sub ldotbelowmacron by ldotbelowmacron.ss02;
+sub llinebelow by llinebelow.ss02;
+sub lcircumflexbelow by lcircumflexbelow.ss02;
diff --git a/src/features/cv06-r.fea b/src/features/cv06-r.fea
new file mode 100644
index 000000000..752a642bc
--- /dev/null
+++ b/src/features/cv06-r.fea
@@ -0,0 +1,14 @@
+cvParameters { FeatUILabelNameID { name "Lower case R with curved tail"; }; };
+sub r by r.1;
+sub rrthook by rrthook.1;
+sub uni024D by uni024D.1;
+sub rdescend by rdescend.1;
+sub racute by racute.1;
+sub rcommaaccent by rcommaaccent.1;
+sub rcaron by rcaron.1;
+sub rdblgrave by rdblgrave.1;
+sub rinvertedbreve by rinvertedbreve.1;
+sub rdotaccent by rdotaccent.1;
+sub rdotbelow by rdotbelow.1;
+sub rdotbelowmacron by rdotbelowmacron.1;
+sub rlinebelow by rlinebelow.1;
diff --git a/src/features/cv07-germandbls.fea b/src/features/cv07-germandbls.fea
new file mode 100644
index 000000000..64556ae2d
--- /dev/null
+++ b/src/features/cv07-germandbls.fea
@@ -0,0 +1,2 @@
+cvParameters { FeatUILabelNameID { name "Alternate German double s"; }; };
+sub germandbls by germandbls.1;
diff --git a/src/features/cv08-i-serif.fea b/src/features/cv08-i-serif.fea
new file mode 100644
index 000000000..0d7835346
--- /dev/null
+++ b/src/features/cv08-i-serif.fea
@@ -0,0 +1,33 @@
+cvParameters { FeatUILabelNameID { name "Upper case i with serif"; }; };
+sub I by I.1;
+sub Idieresis by Idieresis.1;
+sub Idieresisacute by Idieresisacute.1;
+sub Istroke by Istroke.1;
+sub Itildebelow by Itildebelow.1;
+sub Igrave by Igrave.1;
+sub Iacute by Iacute.1;
+sub Icircumflex by Icircumflex.1;
+sub Itilde by Itilde.1;
+sub Imacron by Imacron.1;
+sub Ibreve by Ibreve.1;
+sub Iogonek by Iogonek.1;
+sub Idotaccent by Idotaccent.1;
+sub Icaron by Icaron.1;
+sub Idblgrave by Idblgrave.1;
+sub Iinvertedbreve by Iinvertedbreve.1;
+sub Ihookabove by Ihookabove.1;
+sub Idotbelow by Idotbelow.1;
+sub uni1F38 by uni1F38.1;
+sub uni1F39 by uni1F39.1;
+sub uni1F3A by uni1F3A.1;
+sub uni1F3B by uni1F3B.1;
+sub uni1F3C by uni1F3C.1;
+sub uni1F3D by uni1F3D.1;
+sub uni1F3E by uni1F3E.1;
+sub uni1F3F by uni1F3F.1;
+sub uni1FD8 by uni1FD8.1;
+sub uni1FD9 by uni1FD9.1;
+sub uni1FDA by uni1FDA.1;
+sub uni1FDB by uni1FDB.1;
+sub afii10055 by afii10055.1;
+sub afii10056 by afii10056.1;
diff --git a/src/features/cv09-three.fea b/src/features/cv09-three.fea
new file mode 100644
index 000000000..448a561b7
--- /dev/null
+++ b/src/features/cv09-three.fea
@@ -0,0 +1,5 @@
+cvParameters { FeatUILabelNameID { name "Flat top three"; }; };
+sub three by three.1;
+sub three.tf by three.1.tf;
+sub three.squared by three.1.squared;
+sub three.circled by three.1.circled;
diff --git a/src/features/cv10-g-spur.fea b/src/features/cv10-g-spur.fea
new file mode 100644
index 000000000..58f51ab2d
--- /dev/null
+++ b/src/features/cv10-g-spur.fea
@@ -0,0 +1,11 @@
+cvParameters { FeatUILabelNameID { name "Captital G with spur"; }; };
+sub G by G.1;
+sub Gbar by Gbar.1;
+sub Ghook by Ghook.1;
+sub Gcircumflex by Gcircumflex.1;
+sub Gbreve by Gbreve.1;
+sub Gdotaccent by Gdotaccent.1;
+sub Gcommaaccent by Gcommaaccent.1;
+sub Gcaron by Gcaron.1;
+sub Gacute by Gacute.1;
+sub Gmacron by Gmacron.1;
diff --git a/src/features/cv11-single-storey-a.fea b/src/features/cv11-single-storey-a.fea
new file mode 100644
index 000000000..941f2f540
--- /dev/null
+++ b/src/features/cv11-single-storey-a.fea
@@ -0,0 +1,33 @@
+cvParameters { FeatUILabelNameID { name "Single storey a"; }; };
+sub a by a.1;
+sub aacute by aacute.1;
+sub abreve by abreve.1;
+sub abreveacute by abreveacute.1;
+sub abrevedotbelow by abrevedotbelow.1;
+sub abrevegrave by abrevegrave.1;
+sub abrevehookabove by abrevehookabove.1;
+sub abrevetilde by abrevetilde.1;
+sub acaron by acaron.1;
+sub acircumflex by acircumflex.1;
+sub acircumflexacute by acircumflexacute.1;
+sub acircumflexdotbelow by acircumflexdotbelow.1;
+sub acircumflexgrave by acircumflexgrave.1;
+sub acircumflexhookabove by acircumflexhookabove.1;
+sub acircumflextilde by acircumflextilde.1;
+sub adblgrave by adblgrave.1;
+sub adieresis by adieresis.1;
+sub adieresismacron by adieresismacron.1;
+sub uni0227 by uni0227.1;
+sub adotbelow by adotbelow.1;
+sub adotmacron by adotmacron.1;
+sub agrave by agrave.1;
+sub ahookabove by ahookabove.1;
+sub ainvertedbreve by ainvertedbreve.1;
+sub amacron by amacron.1;
+sub aogonek by aogonek.1;
+sub arighthalfring by arighthalfring.1;
+sub aring by aring.1;
+sub aringacute by aringacute.1;
+sub aringbelow by aringbelow.1;
+sub atilde by atilde.1;
+sub acyrillic by a.1; # acyrillic is just a reference to /a
diff --git a/src/features/dlig.fea b/src/features/dlig.fea
new file mode 100644
index 000000000..cfaa67c56
--- /dev/null
+++ b/src/features/dlig.fea
@@ -0,0 +1,4 @@
+sub exclam question by interrobang;
+sub question exclam by interrobang;
+sub exclamdown questiondown by invertedinterrobang;
+sub questiondown exclamdown by invertedinterrobang;
diff --git a/src/features/frac.fea b/src/features/frac.fea
new file mode 100644
index 000000000..6aad1f76a
--- /dev/null
+++ b/src/features/frac.fea
@@ -0,0 +1,198 @@
+@figures = [
+ zero
+ one
+ two
+ three
+ four
+ five
+ six
+ seven
+ eight
+ nine
+];
+@numerators = [
+ zero.frac
+ one.frac
+ two.frac
+ three.frac
+ four.frac
+ five.frac
+ six.frac
+ seven.frac
+ eight.frac
+ nine.frac
+];
+@numerators2 = [
+ zero.numr
+ one.numr
+ two.numr
+ three.numr
+ four.numr
+ five.numr
+ six.numr
+ seven.numr
+ eight.numr
+ nine.numr
+];
+@denominators = [
+ zero.dnomf
+ one.dnomf
+ two.dnomf
+ three.dnomf
+ four.dnomf
+ five.dnomf
+ six.dnomf
+ seven.dnomf
+ eight.dnomf
+ nine.dnomf
+];
+@denominators2 = [
+ zero.dnom
+ one.dnom
+ two.dnom
+ three.dnom
+ four.dnom
+ five.dnom
+ six.dnom
+ seven.dnom
+ eight.dnom
+ nine.dnom
+];
+@subscripts = [
+ zero.subs
+ one.subs
+ two.subs
+ three.subs
+ four.subs
+ five.subs
+ six.subs
+ seven.subs
+ eight.subs
+ nine.subs
+];
+
+lookup FractionBar {
+ ignore sub slash @figures @figures @figures @figures @figures @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures @figures slash;
+ ignore sub slash @figures @figures @figures slash';
+ ignore sub slash' @figures @figures @figures slash;
+ ignore sub slash @figures @figures slash';
+ ignore sub slash' @figures @figures slash;
+ ignore sub slash @figures slash';
+ ignore sub slash' @figures slash;
+ sub @figures slash' @figures by fraction;
+} FractionBar;
+
+lookup Numerator1 {
+ sub @figures'
+ fraction by @numerators;
+} Numerator1;
+
+lookup Numerator2 {
+ sub @figures'
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator2;
+
+lookup Numerator3 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator3;
+
+lookup Numerator4 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator4;
+
+lookup Numerator5 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator5;
+
+lookup Numerator6 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator6;
+
+lookup Numerator7 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator7;
+
+lookup Numerator8 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator8;
+
+lookup Numerator9 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator9;
+
+lookup Numerator10 {
+ sub @figures'
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ [@numerators @numerators2]
+ fraction by @numerators;
+} Numerator10;
+
+lookup Denominator {
+ sub [fraction @denominators @denominators2 onefraction] @figures' by @denominators;
+ sub [fraction @denominators @denominators2 onefraction] @subscripts' by @denominators;
+} Denominator;
+
+sub @figures space' [@numerators @numerators2] by thinspace;
diff --git a/src/features/liga.fea b/src/features/liga.fea
new file mode 100644
index 000000000..863ce2ba6
--- /dev/null
+++ b/src/features/liga.fea
@@ -0,0 +1,282 @@
+@DASH = [
+ hyphen
+ endash
+ emdash
+];
+@DASH_CASE = [
+ hyphen.case
+ endash.case
+ emdash.case
+];
+
+# ->
+sub hyphen greater by rightArrow;
+sub [endash emdash] greater by rightLongArrow; # legacy
+sub @DASH @DASH greater by rightLongArrow;
+sub @DASH @DASH @DASH greater by rightLongArrow2;
+# <-
+sub less @DASH @DASH by leftLongArrow;
+sub less @DASH @DASH @DASH by leftLongArrow2;
+ignore sub less' hyphen' @Numeral; # ignore e.g. "<-3" ("less than negative")
+sub less' hyphen' by leftArrow;
+sub less [endash emdash] by leftLongArrow; # legacy
+# <->
+sub less rightArrow by leftRightArrow; # <,->
+sub leftArrow greater by leftRightArrow; # <-,-
+sub less rightLongArrow by leftRightLongArrow; # <,-->
+sub leftLongArrow greater by leftRightLongArrow; # <--,>
+
+# x surrounded by numbers, e.g. 3x4 -> 3×4
+sub @Numeral x' @Numeral by multiply; # 3x9
+sub @Numeral @Whitespace x' @Numeral by multiply; # 3 x9
+sub @Numeral @Whitespace @Whitespace x' @Numeral by multiply; # 3 x9
+sub @Numeral x' @Whitespace @Numeral by multiply; # 3x 9
+sub @Numeral @Whitespace x' @Whitespace @Numeral by multiply; # 3 x 9
+sub @Numeral @Whitespace @Whitespace x' @Whitespace @Numeral by multiply; # 3 x 9
+sub @Numeral x' @Whitespace @Whitespace @Numeral by multiply; # 3x 9
+sub @Numeral @Whitespace x' @Whitespace @Whitespace @Numeral by multiply; # 3 x 9
+sub @Numeral @Whitespace @Whitespace x' @Whitespace @Whitespace @Numeral by multiply; # 3 x 9
+
+# * enclosingsquarecomb -> composite
+sub A enclosingsquarecomb by A.squared;
+sub B enclosingsquarecomb by B.squared;
+sub C enclosingsquarecomb by C.squared;
+sub D enclosingsquarecomb by D.squared;
+sub E enclosingsquarecomb by E.squared;
+sub F enclosingsquarecomb by F.squared;
+sub G enclosingsquarecomb by G.squared;
+sub H enclosingsquarecomb by H.squared;
+sub I enclosingsquarecomb by I.squared;
+sub J enclosingsquarecomb by J.squared;
+sub K enclosingsquarecomb by K.squared;
+sub L enclosingsquarecomb by L.squared;
+sub M enclosingsquarecomb by M.squared;
+sub N enclosingsquarecomb by N.squared;
+sub O enclosingsquarecomb by O.squared;
+sub P enclosingsquarecomb by P.squared;
+sub Q enclosingsquarecomb by Q.squared;
+sub R enclosingsquarecomb by R.squared;
+sub S enclosingsquarecomb by S.squared;
+sub T enclosingsquarecomb by T.squared;
+sub U enclosingsquarecomb by U.squared;
+sub V enclosingsquarecomb by V.squared;
+sub W enclosingsquarecomb by W.squared;
+sub X enclosingsquarecomb by X.squared;
+sub Y enclosingsquarecomb by Y.squared;
+sub Z enclosingsquarecomb by Z.squared;
+sub zero enclosingsquarecomb by zero.squared;
+sub one enclosingsquarecomb by one.squared;
+sub two enclosingsquarecomb by two.squared;
+sub three enclosingsquarecomb by three.squared;
+sub four enclosingsquarecomb by four.squared;
+sub five enclosingsquarecomb by five.squared;
+sub six enclosingsquarecomb by six.squared;
+sub seven enclosingsquarecomb by seven.squared;
+sub eight enclosingsquarecomb by eight.squared;
+sub nine enclosingsquarecomb by nine.squared;
+sub zero.slash enclosingsquarecomb by zero.slash.squared;
+sub one.ss01 enclosingsquarecomb by one.ss01.squared;
+sub three.1 enclosingsquarecomb by three.1.squared;
+sub four.ss01 enclosingsquarecomb by four.ss01.squared;
+sub six.ss01 enclosingsquarecomb by six.ss01.squared;
+sub nine.ss01 enclosingsquarecomb by nine.ss01.squared;
+sub exclam enclosingsquarecomb by exclam.squared;
+sub question enclosingsquarecomb by question.squared;
+sub numbersign enclosingsquarecomb by numbersign.squared;
+sub hyphen enclosingsquarecomb by hyphen.squared;
+sub less enclosingsquarecomb by less.squared;
+sub greater enclosingsquarecomb by greater.squared;
+sub equal enclosingsquarecomb by equal.squared;
+sub plus enclosingsquarecomb by plus.squared;
+sub minus enclosingsquarecomb by minus.squared;
+sub multiply enclosingsquarecomb by multiply.squared;
+sub divide enclosingsquarecomb by divide.squared;
+sub upArrow enclosingsquarecomb by upArrow.squared;
+sub downArrow enclosingsquarecomb by downArrow.squared;
+sub leftArrow enclosingsquarecomb by leftArrow.squared;
+sub rightArrow enclosingsquarecomb by rightArrow.squared;
+sub dngb_check enclosingsquarecomb by dngb_check.squared;
+sub dngb_ballotx enclosingsquarecomb by dngb_ballotx.squared;
+
+# enclosingsquarecomb * -> composite
+sub enclosingsquarecomb A by A.squared;
+sub enclosingsquarecomb B by B.squared;
+sub enclosingsquarecomb C by C.squared;
+sub enclosingsquarecomb D by D.squared;
+sub enclosingsquarecomb E by E.squared;
+sub enclosingsquarecomb F by F.squared;
+sub enclosingsquarecomb G by G.squared;
+sub enclosingsquarecomb H by H.squared;
+sub enclosingsquarecomb I by I.squared;
+sub enclosingsquarecomb J by J.squared;
+sub enclosingsquarecomb K by K.squared;
+sub enclosingsquarecomb L by L.squared;
+sub enclosingsquarecomb M by M.squared;
+sub enclosingsquarecomb N by N.squared;
+sub enclosingsquarecomb O by O.squared;
+sub enclosingsquarecomb P by P.squared;
+sub enclosingsquarecomb Q by Q.squared;
+sub enclosingsquarecomb R by R.squared;
+sub enclosingsquarecomb S by S.squared;
+sub enclosingsquarecomb T by T.squared;
+sub enclosingsquarecomb U by U.squared;
+sub enclosingsquarecomb V by V.squared;
+sub enclosingsquarecomb W by W.squared;
+sub enclosingsquarecomb X by X.squared;
+sub enclosingsquarecomb Y by Y.squared;
+sub enclosingsquarecomb Z by Z.squared;
+sub enclosingsquarecomb zero by zero.squared;
+sub enclosingsquarecomb one by one.squared;
+sub enclosingsquarecomb two by two.squared;
+sub enclosingsquarecomb three by three.squared;
+sub enclosingsquarecomb four by four.squared;
+sub enclosingsquarecomb five by five.squared;
+sub enclosingsquarecomb six by six.squared;
+sub enclosingsquarecomb seven by seven.squared;
+sub enclosingsquarecomb eight by eight.squared;
+sub enclosingsquarecomb nine by nine.squared;
+sub enclosingsquarecomb zero.slash by zero.slash.squared;
+sub enclosingsquarecomb one.ss01 by one.ss01.squared;
+sub enclosingsquarecomb three.1 by three.1.squared;
+sub enclosingsquarecomb four.ss01 by four.ss01.squared;
+sub enclosingsquarecomb six.ss01 by six.ss01.squared;
+sub enclosingsquarecomb nine.ss01 by nine.ss01.squared;
+sub enclosingsquarecomb exclam by exclam.squared;
+sub enclosingsquarecomb question by question.squared;
+sub enclosingsquarecomb numbersign by numbersign.squared;
+sub enclosingsquarecomb hyphen by hyphen.squared;
+sub enclosingsquarecomb less by less.squared;
+sub enclosingsquarecomb greater by greater.squared;
+sub enclosingsquarecomb equal by equal.squared;
+sub enclosingsquarecomb plus by plus.squared;
+sub enclosingsquarecomb minus by minus.squared;
+sub enclosingsquarecomb multiply by multiply.squared;
+sub enclosingsquarecomb divide by divide.squared;
+sub enclosingsquarecomb upArrow by upArrow.squared;
+sub enclosingsquarecomb downArrow by downArrow.squared;
+sub enclosingsquarecomb leftArrow by leftArrow.squared;
+sub enclosingsquarecomb rightArrow by rightArrow.squared;
+sub enclosingsquarecomb dngb_check by dngb_check.squared;
+sub enclosingsquarecomb dngb_ballotx by dngb_ballotx.squared;
+
+# * enclosingcirclecomb -> composite
+sub A enclosingcirclecomb by A.circled;
+sub B enclosingcirclecomb by B.circled;
+sub C enclosingcirclecomb by C.circled;
+sub D enclosingcirclecomb by D.circled;
+sub E enclosingcirclecomb by E.circled;
+sub F enclosingcirclecomb by F.circled;
+sub G enclosingcirclecomb by G.circled;
+sub H enclosingcirclecomb by H.circled;
+sub I enclosingcirclecomb by I.circled;
+sub J enclosingcirclecomb by J.circled;
+sub K enclosingcirclecomb by K.circled;
+sub L enclosingcirclecomb by L.circled;
+sub M enclosingcirclecomb by M.circled;
+sub N enclosingcirclecomb by N.circled;
+sub O enclosingcirclecomb by O.circled;
+sub P enclosingcirclecomb by P.circled;
+sub Q enclosingcirclecomb by Q.circled;
+sub R enclosingcirclecomb by R.circled;
+sub S enclosingcirclecomb by S.circled;
+sub T enclosingcirclecomb by T.circled;
+sub U enclosingcirclecomb by U.circled;
+sub V enclosingcirclecomb by V.circled;
+sub W enclosingcirclecomb by W.circled;
+sub X enclosingcirclecomb by X.circled;
+sub Y enclosingcirclecomb by Y.circled;
+sub Z enclosingcirclecomb by Z.circled;
+sub zero enclosingcirclecomb by zero.circled;
+sub one enclosingcirclecomb by one.circled;
+sub two enclosingcirclecomb by two.circled;
+sub three enclosingcirclecomb by three.circled;
+sub four enclosingcirclecomb by four.circled;
+sub five enclosingcirclecomb by five.circled;
+sub six enclosingcirclecomb by six.circled;
+sub seven enclosingcirclecomb by seven.circled;
+sub eight enclosingcirclecomb by eight.circled;
+sub nine enclosingcirclecomb by nine.circled;
+sub zero.slash enclosingcirclecomb by zero.slash.circled;
+sub one.ss01 enclosingcirclecomb by one.ss01.circled;
+sub three.1 enclosingcirclecomb by three.1.circled;
+sub four.ss01 enclosingcirclecomb by four.ss01.circled;
+sub six.ss01 enclosingcirclecomb by six.ss01.circled;
+sub nine.ss01 enclosingcirclecomb by nine.ss01.circled;
+sub exclam enclosingcirclecomb by exclam.circled;
+sub question enclosingcirclecomb by question.circled;
+sub numbersign enclosingcirclecomb by numbersign.circled;
+sub hyphen enclosingcirclecomb by hyphen.circled;
+sub less enclosingcirclecomb by less.circled;
+sub greater enclosingcirclecomb by greater.circled;
+sub equal enclosingcirclecomb by equal.circled;
+sub plus enclosingcirclecomb by plus.circled;
+sub minus enclosingcirclecomb by minus.circled;
+sub multiply enclosingcirclecomb by multiply.circled;
+sub divide enclosingcirclecomb by divide.circled;
+sub upArrow enclosingcirclecomb by upArrow.circled;
+sub downArrow enclosingcirclecomb by downArrow.circled;
+sub leftArrow enclosingcirclecomb by leftArrow.circled;
+sub rightArrow enclosingcirclecomb by rightArrow.circled;
+sub dngb_check enclosingcirclecomb by dngb_check.circled;
+sub dngb_ballotx enclosingcirclecomb by dngb_ballotx.circled;
+
+# enclosingcirclecomb * -> composite
+sub enclosingcirclecomb A by A.circled;
+sub enclosingcirclecomb B by B.circled;
+sub enclosingcirclecomb C by C.circled;
+sub enclosingcirclecomb D by D.circled;
+sub enclosingcirclecomb E by E.circled;
+sub enclosingcirclecomb F by F.circled;
+sub enclosingcirclecomb G by G.circled;
+sub enclosingcirclecomb H by H.circled;
+sub enclosingcirclecomb I by I.circled;
+sub enclosingcirclecomb J by J.circled;
+sub enclosingcirclecomb K by K.circled;
+sub enclosingcirclecomb L by L.circled;
+sub enclosingcirclecomb M by M.circled;
+sub enclosingcirclecomb N by N.circled;
+sub enclosingcirclecomb O by O.circled;
+sub enclosingcirclecomb P by P.circled;
+sub enclosingcirclecomb Q by Q.circled;
+sub enclosingcirclecomb R by R.circled;
+sub enclosingcirclecomb S by S.circled;
+sub enclosingcirclecomb T by T.circled;
+sub enclosingcirclecomb U by U.circled;
+sub enclosingcirclecomb V by V.circled;
+sub enclosingcirclecomb W by W.circled;
+sub enclosingcirclecomb X by X.circled;
+sub enclosingcirclecomb Y by Y.circled;
+sub enclosingcirclecomb Z by Z.circled;
+sub enclosingcirclecomb zero by zero.circled;
+sub enclosingcirclecomb one by one.circled;
+sub enclosingcirclecomb two by two.circled;
+sub enclosingcirclecomb three by three.circled;
+sub enclosingcirclecomb four by four.circled;
+sub enclosingcirclecomb five by five.circled;
+sub enclosingcirclecomb six by six.circled;
+sub enclosingcirclecomb seven by seven.circled;
+sub enclosingcirclecomb eight by eight.circled;
+sub enclosingcirclecomb nine by nine.circled;
+sub enclosingcirclecomb zero.slash by zero.slash.circled;
+sub enclosingcirclecomb one.ss01 by one.ss01.circled;
+sub enclosingcirclecomb three.1 by three.1.circled;
+sub enclosingcirclecomb four.ss01 by four.ss01.circled;
+sub enclosingcirclecomb six.ss01 by six.ss01.circled;
+sub enclosingcirclecomb nine.ss01 by nine.ss01.circled;
+sub enclosingcirclecomb exclam by exclam.circled;
+sub enclosingcirclecomb question by question.circled;
+sub enclosingcirclecomb numbersign by numbersign.circled;
+sub enclosingcirclecomb hyphen by hyphen.circled;
+sub enclosingcirclecomb less by less.circled;
+sub enclosingcirclecomb greater by greater.circled;
+sub enclosingcirclecomb equal by equal.circled;
+sub enclosingcirclecomb plus by plus.circled;
+sub enclosingcirclecomb minus by minus.circled;
+sub enclosingcirclecomb multiply by multiply.circled;
+sub enclosingcirclecomb divide by divide.circled;
+sub enclosingcirclecomb upArrow by upArrow.circled;
+sub enclosingcirclecomb downArrow by downArrow.circled;
+sub enclosingcirclecomb leftArrow by leftArrow.circled;
+sub enclosingcirclecomb rightArrow by rightArrow.circled;
+sub enclosingcirclecomb dngb_check by dngb_check.circled;
+sub enclosingcirclecomb dngb_ballotx by dngb_ballotx.circled;
diff --git a/src/features/salt.fea b/src/features/salt.fea
new file mode 100644
index 000000000..2d3fc9621
--- /dev/null
+++ b/src/features/salt.fea
@@ -0,0 +1,81 @@
+sub one by one.ss01;
+sub one.tf by one.tf.ss01;
+sub three by three.1;
+sub three.tf by three.1.tf;
+sub four by four.ss01;
+sub four.tf by four.tf.ss01;
+sub six by six.ss01;
+sub six.tf by six.tf.ss01;
+sub nine by nine.ss01;
+sub nine.tf by nine.tf.ss01;
+
+sub a by a.1;
+sub aacute by aacute.1;
+sub abreve by abreve.1;
+sub abreveacute by abreveacute.1;
+sub abrevedotbelow by abrevedotbelow.1;
+sub abrevegrave by abrevegrave.1;
+sub abrevehookabove by abrevehookabove.1;
+sub abrevetilde by abrevetilde.1;
+sub acaron by acaron.1;
+sub acircumflex by acircumflex.1;
+sub acircumflexacute by acircumflexacute.1;
+sub acircumflexdotbelow by acircumflexdotbelow.1;
+sub acircumflexgrave by acircumflexgrave.1;
+sub acircumflexhookabove by acircumflexhookabove.1;
+sub acircumflextilde by acircumflextilde.1;
+sub adblgrave by adblgrave.1;
+sub adieresis by adieresis.1;
+sub adieresismacron by adieresismacron.1;
+sub uni0227 by uni0227.1;
+sub adotbelow by adotbelow.1;
+sub adotmacron by adotmacron.1;
+sub agrave by agrave.1;
+sub ahookabove by ahookabove.1;
+sub ainvertedbreve by ainvertedbreve.1;
+sub amacron by amacron.1;
+sub aogonek by aogonek.1;
+sub arighthalfring by arighthalfring.1;
+sub aring by aring.1;
+sub aringacute by aringacute.1;
+sub aringbelow by aringbelow.1;
+sub atilde by atilde.1;
+
+sub l by l.ss02;
+sub lslash by lslash.ss02;
+sub lbar by lbar.ss02;
+sub lmidtilde by lmidtilde.ss02;
+sub lbelt by lbelt.ss02;
+sub ldot by ldot.ss02;
+sub lacute by lacute.ss02;
+sub lcommaaccent by lcommaaccent.ss02;
+sub lcaron by lcaron.ss02;
+sub ldotbelow by ldotbelow.ss02;
+sub ldotbelowmacron by ldotbelowmacron.ss02;
+sub llinebelow by llinebelow.ss02;
+sub lcircumflexbelow by lcircumflexbelow.ss02;
+
+sub r by r.1;
+sub rrthook by rrthook.1;
+sub uni024D by uni024D.1;
+sub rdescend by rdescend.1;
+sub racute by racute.1;
+sub rcommaaccent by rcommaaccent.1;
+sub rcaron by rcaron.1;
+sub rdblgrave by rdblgrave.1;
+sub rinvertedbreve by rinvertedbreve.1;
+sub rdotaccent by rdotaccent.1;
+sub rdotbelow by rdotbelow.1;
+sub rdotbelowmacron by rdotbelowmacron.1;
+sub rlinebelow by rlinebelow.1;
+
+sub G by G.1;
+sub Gbar by Gbar.1;
+sub Ghook by Ghook.1;
+sub Gcircumflex by Gcircumflex.1;
+sub Gbreve by Gbreve.1;
+sub Gdotaccent by Gdotaccent.1;
+sub Gcommaaccent by Gcommaaccent.1;
+sub Gcaron by Gcaron.1;
+sub Gacute by Gacute.1;
+sub Gmacron by Gmacron.1;
diff --git a/src/features/ss01-alt-digits.fea b/src/features/ss01-alt-digits.fea
new file mode 100644
index 000000000..54cf36599
--- /dev/null
+++ b/src/features/ss01-alt-digits.fea
@@ -0,0 +1,21 @@
+featureNames { name "Alternate digits"; };
+sub one by one.ss01;
+sub one.tf by one.tf.ss01;
+sub one.squared by one.ss01.squared;
+sub one.circled by one.ss01.circled;
+sub three by three.1;
+sub three.tf by three.1.tf;
+sub three.squared by three.1.squared;
+sub three.circled by three.1.circled;
+sub four by four.ss01;
+sub four.tf by four.tf.ss01;
+sub four.squared by four.ss01.squared;
+sub four.circled by four.ss01.circled;
+sub six by six.ss01;
+sub six.tf by six.tf.ss01;
+sub six.squared by six.ss01.squared;
+sub six.circled by six.ss01.circled;
+sub nine by nine.ss01;
+sub nine.tf by nine.tf.ss01;
+sub nine.squared by nine.ss01.squared;
+sub nine.circled by nine.ss01.circled;
diff --git a/src/features/ss02-disambiguation.fea b/src/features/ss02-disambiguation.fea
new file mode 100644
index 000000000..86a554807
--- /dev/null
+++ b/src/features/ss02-disambiguation.fea
@@ -0,0 +1,51 @@
+featureNames { name "Disambiguation"; };
+sub l by l.ss02;
+sub lslash by lslash.ss02;
+sub lbar by lbar.ss02;
+sub lmidtilde by lmidtilde.ss02;
+sub lbelt by lbelt.ss02;
+sub ldot by ldot.ss02;
+sub lacute by lacute.ss02;
+sub lcommaaccent by lcommaaccent.ss02;
+sub lcaron by lcaron.ss02;
+sub ldotbelow by ldotbelow.ss02;
+sub ldotbelowmacron by ldotbelowmacron.ss02;
+sub llinebelow by llinebelow.ss02;
+sub lcircumflexbelow by lcircumflexbelow.ss02;
+sub zero by zero.slash;
+sub zero.tf by zero.tf.slash;
+sub zero.squared by zero.slash.squared;
+sub zero.circled by zero.slash.circled;
+sub germandbls by germandbls.1;
+sub I by I.1;
+sub Idieresis by Idieresis.1;
+sub Idieresisacute by Idieresisacute.1;
+sub Istroke by Istroke.1;
+sub Itildebelow by Itildebelow.1;
+sub Igrave by Igrave.1;
+sub Iacute by Iacute.1;
+sub Icircumflex by Icircumflex.1;
+sub Itilde by Itilde.1;
+sub Imacron by Imacron.1;
+sub Ibreve by Ibreve.1;
+sub Iogonek by Iogonek.1;
+sub Idotaccent by Idotaccent.1;
+sub Icaron by Icaron.1;
+sub Idblgrave by Idblgrave.1;
+sub Iinvertedbreve by Iinvertedbreve.1;
+sub Ihookabove by Ihookabove.1;
+sub Idotbelow by Idotbelow.1;
+sub uni1F38 by uni1F38.1;
+sub uni1F39 by uni1F39.1;
+sub uni1F3A by uni1F3A.1;
+sub uni1F3B by uni1F3B.1;
+sub uni1F3C by uni1F3C.1;
+sub uni1F3D by uni1F3D.1;
+sub uni1F3E by uni1F3E.1;
+sub uni1F3F by uni1F3F.1;
+sub uni1FD8 by uni1FD8.1;
+sub uni1FD9 by uni1FD9.1;
+sub uni1FDA by uni1FDA.1;
+sub uni1FDB by uni1FDB.1;
+sub afii10055 by afii10055.1;
+sub afii10056 by afii10056.1;
diff --git a/src/features/ss03-r-curve.fea b/src/features/ss03-r-curve.fea
new file mode 100644
index 000000000..fe42872dc
--- /dev/null
+++ b/src/features/ss03-r-curve.fea
@@ -0,0 +1,332 @@
+featureNames { name "Lower case r curves into round neighbors"; };
+# curved "r" when it meets a curved shape, e.g. "ro"
+@straight_r = [
+ r
+ rrthook
+ uni024D
+ rdescend
+ racute
+ rcommaaccent
+ rcaron
+ rdblgrave
+ rinvertedbreve
+ rdotaccent
+ rdotbelow
+ rdotbelowmacron
+ rlinebelow
+];
+@curved_r = [
+ r.1
+ rrthook.1
+ uni024D.1
+ rdescend.1
+ racute.1
+ rcommaaccent.1
+ rcaron.1
+ rdblgrave.1
+ rinvertedbreve.1
+ rdotaccent.1
+ rdotbelow.1
+ rdotbelowmacron.1
+ rlinebelow.1
+];
+
+# lower case-sized glyphs where the left side is curved, like "o"
+@lc_left_side_curved = [
+ a
+ adieresis
+ atilde
+ arighthalfring
+ agrave
+ aacute
+ acircumflex
+ aring
+ amacron
+ abreve
+ aogonek
+ acaron
+ adieresismacron
+ adotmacron
+ aringacute
+ adblgrave
+ ainvertedbreve
+ uni0227
+ aringbelow
+ adotbelow
+ ahookabove
+ acircumflexacute
+ acircumflexgrave
+ acircumflexhookabove
+ acircumflextilde
+ acircumflexdotbelow
+ abreveacute
+ abrevegrave
+ abrevehookabove
+ abrevetilde
+ abrevedotbelow
+ acyrillic
+ abrevecyrillic
+ adieresiscyrillic
+ ae
+ aemacron
+ aeacute
+ aiecyrillic
+ c
+ uni023C
+ chook
+ ccurl
+ ccedilla
+ cacute
+ ccircumflex
+ cdotaccent
+ ccaron
+ ccedillaacute
+ sigmalunatesymbolgreek
+ escyrillic
+ d
+ dcroat
+ drthook
+ dhook
+ dtopbar
+ uni0221
+ dcaron
+ ddotaccent
+ ddotbelow
+ dlinebelow
+ dcedilla
+ dcircumflexbelow
+ dz
+ dzcaron
+ dzcurl
+ dyogh
+ dong
+ e
+ edieresis
+ uni0247
+ egrave
+ eacute
+ ecircumflex
+ emacron
+ ebreve
+ edotaccent
+ eogonek
+ ecaron
+ edblgrave
+ einvertedbreve
+ uni0229
+ emacrongrave
+ emacronacute
+ ecircumflexbelow
+ etildebelow
+ ecedillabreve
+ edotbelow
+ ehookabove
+ etilde
+ ecircumflexacute
+ ecircumflexgrave
+ ecircumflexhookabove
+ ecircumflextilde
+ ecircumflexdotbelow
+ iecyrillic
+ uni0450
+ iocyrillic
+ iebrevecyrillic
+ eturn
+ g
+ ghook
+ gbar
+ gcircumflex
+ gbreve
+ gdotaccent
+ gcommaaccent
+ gcaron
+ gacute
+ gmacron
+ o
+ odieresis
+ otilde
+ oslash
+ ohorn
+ ograve
+ oacute
+ ocircumflex
+ omacron
+ obreve
+ ohungarumlaut
+ ocaron
+ oogonek
+ oogonekmacron
+ odblgrave
+ oinvertedbreve
+ uni022B
+ uni022D
+ uni022F
+ uni0231
+ otildeacute
+ otildedieresis
+ omacrongrave
+ omacronacute
+ odotbelow
+ ohookabove
+ ocircumflexacute
+ ocircumflexgrave
+ ocircumflexhookabove
+ ocircumflextilde
+ ocircumflexdotbelow
+ ohornacute
+ ohorngrave
+ ohornhookabove
+ ohorntilde
+ ohorndotbelow
+ oslashacute
+ omicron
+ omicrontonos
+ uni1F40
+ uni1F41
+ uni1F42
+ uni1F43
+ uni1F44
+ uni1F45
+ uni1F78
+ fitacyrillic
+ obar
+ ocyrillic
+ odieresiscyrillic
+ oe
+ ukcyrillic
+ q
+ qhook
+ qrthook
+ s
+ srthook
+ uni023F
+ sacute
+ scircumflex
+ scedilla
+ scaron
+ scommaaccent
+ sdotaccent
+ sdotbelow
+ sacutedotaccent
+ scarondotaccent
+ sdotbelowdotaccent
+ dzecyrillic
+ tonetwo
+ eth
+ alpha
+ alphatonos
+ uni1F00
+ uni1F01
+ uni1F02
+ uni1F03
+ uni1F04
+ uni1F05
+ uni1F06
+ uni1F07
+ uni1F70
+ uni1F80
+ uni1F81
+ uni1F82
+ uni1F83
+ uni1F84
+ uni1F85
+ uni1F86
+ uni1F87
+ uni1FB0
+ uni1FB1
+ uni1FB2
+ uni1FB3
+ uni1FB4
+ uni1FB6
+ uni1FB7
+ delta
+ epsilon
+ epsilontonos
+ epsilonclosed
+ epsilon1
+ epsilon1rev
+ epsilon1revclosed
+ epsilon1revhook
+ uni1F10
+ uni1F11
+ uni1F12
+ uni1F13
+ uni1F14
+ uni1F15
+ uni1F72
+ rho
+ uni1FE4
+ uni1FE5
+ uni03FC
+ sigma1
+ sigma
+ phi
+ phigreek
+ omega
+ omegatonos
+ uni1F60
+ uni1F61
+ uni1F62
+ uni1F63
+ uni1F64
+ uni1F65
+ uni1F66
+ uni1F67
+ uni1F7C
+ uni1FA0
+ uni1FA1
+ uni1FA2
+ uni1FA3
+ uni1FA4
+ uni1FA5
+ uni1FA6
+ uni1FA7
+ uni1FF2
+ uni1FF3
+ uni1FF4
+ uni1FF6
+ uni1FF7
+ zecyrillic
+ efcyrillic
+ ereversedcyrillic
+ iacyrillic
+ ecyrillic
+ haabkhasiancyrillic
+ cent
+ manat
+ six.ss01
+ ascript
+ ascript_uni02DE
+ erev
+ schwa
+ schwahook
+ oopen
+ uni0238
+ uni0239
+ uni2184
+ aogonek.NAV
+ eogonek.NAV
+ oogonek.NAV
+ zedescendercyrillic
+ esdescendercyrillic
+ schwacyrillic
+ schwadieresiscyrillic
+ zedieresiscyrillic
+ obarredcyrillic
+ obarreddieresiscyrillic
+ uni04ED
+ koppacyrillic
+ uni037B
+ uni037C
+ uni037D
+ uni03D9
+ stigma
+ rho1
+ uni1F71
+ uni1F73
+ uni1F79
+ uni217D
+ uni217E
+];
+
+sub @straight_r' @lc_left_side_curved by @curved_r;
diff --git a/src/features/subs.fea b/src/features/subs.fea
new file mode 100644
index 000000000..7bba3e434
--- /dev/null
+++ b/src/features/subs.fea
@@ -0,0 +1,43 @@
+sub a by a.subs;
+sub b by b.subs;
+sub c by c.subs;
+sub d by d.subs;
+sub e by e.subs;
+sub f by f.subs;
+sub g by g.subs;
+sub h by h.subs;
+sub i by i.subs;
+sub j by j.subs;
+sub k by k.subs;
+sub [l l.ss02] by l.subs;
+sub m by m.subs;
+sub n by n.subs;
+sub o by o.subs;
+sub p by p.subs;
+sub q by q.subs;
+sub [r r.1] by r.subs;
+sub s by s.subs;
+sub t by t.subs;
+sub u by u.subs;
+sub v by v.subs;
+sub w by w.subs;
+sub x by x.subs;
+sub y by y.subs;
+sub z by z.subs;
+sub [zero zero.slash zero.tf zero.tf.slash] by zero.subs;
+sub [one one.ss01 one.tf one.tf.ss01] by one.subs;
+sub [two two.tf] by two.subs;
+sub [three three.1 three.tf three.1.tf] by three.subs;
+sub [four four.ss01 four.tf four.tf.ss01] by four.subs;
+sub [five five.tf] by five.subs;
+sub [six six.ss01 six.tf six.tf.ss01] by six.subs;
+sub [seven seven.tf] by seven.subs;
+sub [eight eight.tf] by eight.subs;
+sub [nine nine.ss01 nine.tf nine.tf.ss01] by nine.subs;
+sub [parenleft parenleft.case] by parenleft.subs;
+sub [parenright parenright.case] by parenright.subs;
+sub [bracketleft bracketleft.case] by bracketleft.subs;
+sub [bracketright bracketright.case] by bracketright.subs;
+sub [plus plus.case] by plus.subs;
+sub [minus minus.case hyphen hyphen.case] by minus.subs;
+sub [equal equal.case] by equal.subs;
diff --git a/src/features/sups.fea b/src/features/sups.fea
new file mode 100644
index 000000000..3396dba1b
--- /dev/null
+++ b/src/features/sups.fea
@@ -0,0 +1,43 @@
+sub a by a.sups;
+sub b by b.sups;
+sub c by c.sups;
+sub d by d.sups;
+sub e by e.sups;
+sub f by f.sups;
+sub g by g.sups;
+sub h by h.sups;
+sub i by i.sups;
+sub j by j.sups;
+sub k by k.sups;
+sub [l l.ss02] by l.sups;
+sub m by m.sups;
+sub n by n.sups;
+sub o by o.sups;
+sub p by p.sups;
+sub q by q.sups;
+sub [r r.1] by r.sups;
+sub s by s.sups;
+sub t by t.sups;
+sub u by u.sups;
+sub v by v.sups;
+sub w by w.sups;
+sub x by x.sups;
+sub y by y.sups;
+sub z by z.sups;
+sub [zero zero.slash zero.tf zero.tf.slash] by zero.sups;
+sub [one one.ss01 one.tf one.tf.ss01] by one.sups;
+sub [two two.tf] by two.sups;
+sub [three three.1 three.tf three.1.tf] by three.sups;
+sub [four four.ss01 four.tf four.tf.ss01] by four.sups;
+sub [five five.tf] by five.sups;
+sub [six six.ss01 six.tf six.tf.ss01] by six.sups;
+sub [seven seven.tf] by seven.sups;
+sub [eight eight.tf] by eight.sups;
+sub [nine nine.ss01 nine.tf nine.tf.ss01] by nine.sups;
+sub [parenleft parenleft.case] by parenleft.sups;
+sub [parenright parenright.case] by parenright.sups;
+sub [bracketleft bracketleft.case] by bracketleft.sups;
+sub [bracketright bracketright.case] by bracketright.sups;
+sub [plus plus.case] by plus.sups;
+sub [minus minus.case hyphen hyphen.case] by minus.sups;
+sub [equal equal.case] by equal.sups;
diff --git a/src/features/zero.fea b/src/features/zero.fea
new file mode 100644
index 000000000..d06339d71
--- /dev/null
+++ b/src/features/zero.fea
@@ -0,0 +1,4 @@
+sub zero by zero.slash;
+sub zero.tf by zero.tf.slash;
+sub zero.circled by zero.slash.circled;
+sub zero.squared by zero.slash.squared;