Backed out changeset e78abc802629 (bug 1920832) for causing bc failures on browser_in...
[gecko.git] / layout / reftests / font-features / font-variant-features.js
blob56856637398734979f3e0be462004bb7e7f669c1
2 // data associated with gsubtest test font for testing font features
4 // prefix
5 gPrefix = "";
7 // equivalent properties
8 // setting prop: value should match the specific feature settings listed
9 //
10 // each of these tests evaluate whether a given feature is enabled as required
11 // and also whether features that shouldn't be enabled are or not.
12 var gPropertyData = [
13   // font-variant (shorthand)
14   // valid values
15   { prop: "font-variant", value: "normal", features: {"smcp": 0} },
16   { prop: "font-variant", value: "small-caps", features: {"smcp": 1, "c2sc": 0} },
17   { prop: "font-variant", value: "none", features: {"liga": 0, "dlig": 0, "clig": 0, "calt": 0, "hlig": 0} },
18   { prop: "font-variant", value: "all-small-caps", features: {"smcp": 1, "c2sc": 1, "pcap": 0} },
19   { prop: "font-variant", value: "common-ligatures no-discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
20   { prop: "font-variant", value: "proportional-nums slashed-zero diagonal-fractions oldstyle-nums ordinal", features: {"frac": 1, "afrc": 0, "tnum": 0, "pnum": 1, "onum": 1, "ordn": 1, "zero": 1} },
21   { prop: "font-variant", value: "all-small-caps traditional", features: {"smcp": 1, "c2sc": 1, "pcap": 0, "trad": 1, "jp04": 0} },
22   { prop: "font-variant", value: "styleset(out-of-bounds1, out-of-bounds2) traditional", features: {"ss00": 0, "ss01": 0, "ss99": 0, "trad": 1} }, // out-of-bounds values but not invalid syntax
23   { prop: "font-variant", value: "styleset(ok-alt-a, ok-alt-b) historical-forms", features: {"ss01": 1, "ss02": 0, "ss03": 1, "ss04": 0, "ss05": 1, "ss19": 1, "ss20": 0, "hist": 1, "hlig": 0} },
24   { prop: "font-variant", value: "traditional historical-forms styleset(ok-alt-a, ok-alt-b)", features: {"trad": 1, "ss01": 1, "ss02": 0, "ss03": 1, "ss04": 0, "ss05": 1, "ss19": 1, "ss20": 0, "hist": 1, "hlig": 0} },
25   { prop: "font-variant", value: "styleset(scope-test2)", features: {"ss23": 0, "ss24": 1, "ss01": 1} },
26   { prop: "font-variant", value: "character-variant(scope-test2)", features: {"cv23": 2, "cv24": 0, "cv01": 0} },
28   // invalid values
29   { prop: "font-variant", value: "normal small-caps", features: {"smcp": 0}, invalid: true },
30   { prop: "font-variant", value: "common-ligatures none", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
31   { prop: "font-variant", value: "none common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
32   { prop: "font-variant", value: "small-caps potato", features: {"smcp": 0}, invalid: true },
33   { prop: "font-variant", value: "common-ligatures traditional no-common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "trad": 0}, invalid: true },
34   { prop: "font-variant", value: "common-ligatures traditional common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "trad": 0}, invalid: true },
35   { prop: "font-variant", value: "small-caps jis83 all-small-caps", features: {"smcp": 0, "c2sc": 0, "jp83": 0}, invalid: true },
36   { prop: "font-variant", value: "lining-nums traditional slashed-zero ordinal normal", features: {"lnum": 0, "onum": 0, "zero": 0, "trad": 0}, invalid: true },
37   { prop: "font-variant", value: "diagonal-fractions stacked-fractions", features: {"frac": 0, "afrc": 0}, invalid: true },
38   { prop: "font-variant", value: "stacked-fractions diagonal-fractions historical-ligatures", features: {"frac": 0, "afrc": 0, "hlig": 0}, invalid: true },
39   { prop: "font-variant", value: "super sub", features: {"subs": 0, "sups": 0}, invalid: true },
40   { prop: "font-variant", value: "super historical-ligatures sub", features: {"subs": 0, "sups": 0, "hlig": 0}, invalid: true },
41   { prop: "font-variant", value: "annotation(circled) annotation(circled)", features: {"nalt": 0, "lnum": 0, "onum": 0, "pnum": 0}, invalid: true },
43   // font-variant-alternates
44   // valid values
45   { prop: "font-variant-alternates", value: "normal", features: {"salt": 0, "swsh": 0} },
46   { prop: "font-variant-alternates", value: "historical-forms", features: {"hist": 1, "hlig": 0} },
47   { prop: "font-variant-alternates", value: "styleset(ok-alt-a, ok-alt-b)", features: {"ss01": 1, "ss02": 0, "ss03": 1, "ss04": 0, "ss05": 1, "ss19": 1, "ss20": 0} },
48   { prop: "font-variant-alternates", value: "styleset(ok-alt-a, ok-alt-b) historical-forms", features: {"ss01": 1, "ss02": 0, "ss03": 1, "ss04": 0, "ss05": 1, "ss19": 1, "ss20": 0, "hist": 1, "hlig": 0} },
49   { prop: "font-variant-alternates", value: "historical-forms styleset(ok-alt-a, ok-alt-b)", features: {"ss01": 1, "ss02": 0, "ss03": 1, "ss04": 0, "ss05": 1, "ss19": 1, "ss20": 0, "hist": 1, "hlig": 0} },
50   { prop: "font-variant-alternates", value: "character-variant(ok-1)", features: {"cv78": 2, "cv79": 0, "cv77": 0} },
51   { prop: "font-variant-alternates", value: "character-variant(ok-1, ok-3)", features: {"cv78": 2, "cv79": 0, "cv77": 0, "cv23": 1, "cv22": 0, "cv24": 0} },
52   { prop: "font-variant-alternates", value: "annotation(circled)", features: {"nalt": 1} },
53   { prop: "font-variant-alternates", value: "styleset(out-of-bounds1, out-of-bounds2)", features: {"ss00": 0, "ss01": 0, "ss99": 0} }, // out-of-bounds values but not invalid syntax
54   { prop: "font-variant-alternates", value: "styleset(circled)", features: {"nalt": 0, "ss00": 0, "ss01": 0} }, // circled defined for annotation not styleset
55   { prop: "font-variant-alternates", value: "styleset(scope-test1)", features: {"ss23": 1, "ss24": 0} },
56   { prop: "font-variant-alternates", value: "character-variant(scope-test1)", features: {"cv23": 0, "cv24": 1} },
57   { prop: "font-variant-alternates", value: "styleset(scope-test2)", features: {"ss23": 0, "ss24": 1, "ss01": 1} },
58   { prop: "font-variant-alternates", value: "character-variant(scope-test2)", features: {"cv23": 2, "cv24": 0, "cv01": 0} },
59   { prop: "font-variant-alternates", value: "character-variant(overlap1, overlap2)", features: {"cv23": 2} },
60   { prop: "font-variant-alternates", value: "character-variant(overlap2, overlap1)", features: {"cv23": 1} },
62   // invalid values
63   { prop: "font-variant-alternates", value: "historical-forms normal", features: {"hist": 0}, invalid: true },
64   { prop: "font-variant-alternates", value: "historical-forms historical-forms", features: {"hist": 0}, invalid: true },
65   { prop: "font-variant-alternates", value: "swash", features: {"swsh": 0}, invalid: true },
66   { prop: "font-variant-alternates", value: "swash(3)", features: {"swsh": 0}, invalid: true },
67   { prop: "font-variant-alternates", value: "annotation(a, b)", features: {"nalt": 0}, invalid: true },
68   { prop: "font-variant-alternates", value: "ornaments(a,b)", features: {"ornm": 0, "nalt": 0}, invalid: true },
70   // font-variant-caps
71   // valid values
72   { prop: "font-variant-caps", value: "normal", features: {"smcp": 0} },
73   { prop: "font-variant-caps", value: "small-caps", features: {"smcp": 1, "c2sc": 0} },
74   { prop: "font-variant-caps", value: "all-small-caps", features: {"smcp": 1, "c2sc": 1, "pcap": 0} },
75   { prop: "font-variant-caps", value: "petite-caps", features: {"pcap": 1, "smcp": 0} },
76   { prop: "font-variant-caps", value: "all-petite-caps", features: {"c2pc": 1, "pcap": 1, "smcp": 0} },
77   { prop: "font-variant-caps", value: "titling-caps", features: {"titl": 1, "smcp": 0} },
78   { prop: "font-variant-caps", value: "unicase", features: {"unic": 1, "titl": 0} },
80   // invalid values
81   { prop: "font-variant-caps", value: "normal small-caps", features: {"smcp": 0}, invalid: true },
82   { prop: "font-variant-caps", value: "small-caps potato", features: {"smcp": 0}, invalid: true },
83   { prop: "font-variant-caps", value: "small-caps petite-caps", features: {"smcp": 0, "pcap": 0}, invalid: true },
84   { prop: "font-variant-caps", value: "small-caps all-small-caps", features: {"smcp": 0, "c2sc": 0}, invalid: true },
85   { prop: "font-variant-caps", value: "small-cap", features: {"smcp": 0}, invalid: true },
87   // font-variant-east-asian
88   // valid values
89   { prop: "font-variant-east-asian", value: "jis78", features: {"jp78": 1, "jp04": 0} },
90   { prop: "font-variant-east-asian", value: "jis83", features: {"jp83": 1, "jp04": 0} },
91   { prop: "font-variant-east-asian", value: "jis90", features: {"jp90": 1, "jp04": 0} },
92   { prop: "font-variant-east-asian", value: "jis04", features: {"jp04": 1, "jp78": 0} },
93   { prop: "font-variant-east-asian", value: "simplified", features: {"smpl": 1, "jp04": 0} },
94   { prop: "font-variant-east-asian", value: "traditional", features: {"trad": 1, "jp04": 0} },
95   { prop: "font-variant-east-asian", value: "full-width", features: {"fwid": 1, "jp04": 0} },
96   { prop: "font-variant-east-asian", value: "proportional-width", features: {"pwid": 1, "jp04": 0} },
97   { prop: "font-variant-east-asian", value: "ruby", features: {"ruby": 1, "jp04": 0} },
98   { prop: "font-variant-east-asian", value: "jis78 full-width", features: {"jp78": 1, "fwid": 1, "jp83": 0} },
99   { prop: "font-variant-east-asian", value: "jis78 full-width ruby", features: {"jp78": 1, "fwid": 1, "jp83": 0, "ruby": 1} },
100   { prop: "font-variant-east-asian", value: "simplified proportional-width", features: {"smpl": 1, "pwid": 1, "jp83": 0} },
101   { prop: "font-variant-east-asian", value: "ruby simplified", features: {"ruby": 1, "smpl": 1, "trad": 0} },
103   // invalid values
104   { prop: "font-variant-east-asian", value: "ruby normal", features: {"ruby": 0}, invalid: true },
105   { prop: "font-variant-east-asian", value: "jis90 jis04", features: {"jp90": 0, "jp04": 0}, invalid: true },
106   { prop: "font-variant-east-asian", value: "simplified traditional", features: {"smpl": 0, "trad": 0}, invalid: true },
107   { prop: "font-variant-east-asian", value: "full-width proportional-width", features: {"fwid": 0, "pwid": 0}, invalid: true },
108   { prop: "font-variant-east-asian", value: "ruby simplified ruby", features: {"ruby": 0, "smpl": 0, "jp04": 0}, invalid: true },
109   { prop: "font-variant-east-asian", value: "jis78 ruby simplified", features: {"ruby": 0, "smpl": 0, "jp78": 0}, invalid: true },
111   // font-variant-ligatures
112   // valid values
113   { prop: "font-variant-ligatures", value: "none", features: {"liga": 0, "dlig": 0, "clig": 0, "calt": 0, "hlig": 0} },
114   { prop: "font-variant-ligatures", value: "normal", features: {"liga": 1, "dlig": 0} },
115   { prop: "font-variant-ligatures", value: "common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
116   { prop: "font-variant-ligatures", value: "no-common-ligatures", features: {"liga": 0, "clig": 0, "dlig": 0, "hlig": 0, "calt": 1} },
117   { prop: "font-variant-ligatures", value: "discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 1, "hlig": 0, "calt": 1} },
118   { prop: "font-variant-ligatures", value: "no-discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
119   { prop: "font-variant-ligatures", value: "historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 1, "calt": 1} },
120   { prop: "font-variant-ligatures", value: "no-historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
121   { prop: "font-variant-ligatures", value: "contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
122   { prop: "font-variant-ligatures", value: "no-contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 0} },
123   { prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
124   { prop: "font-variant-ligatures", value: "historical-ligatures no-common-ligatures", features: {"clig": 0, "liga": 0, "dlig": 0, "hlig": 1, "calt": 1} },
125   { prop: "font-variant-ligatures", value: "no-historical-ligatures discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 1, "hlig": 0, "calt": 1} },
126   { prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures historical-ligatures no-contextual", features: {"clig": 1, "dlig": 0, "hlig": 1, "liga": 1, "calt": 0} },
128   // invalid values
129   { prop: "font-variant-ligatures", value: "common-ligatures none", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
130   { prop: "font-variant-ligatures", value: "none common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
131   { prop: "font-variant-ligatures", value: "common-ligatures normal", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
132   { prop: "font-variant-ligatures", value: "common-ligatures no-common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
133   { prop: "font-variant-ligatures", value: "common-ligatures common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
134   { prop: "font-variant-ligatures", value: "no-historical-ligatures historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0}, invalid: true },
135   { prop: "font-variant-ligatures", value: "no-contextual contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0}, invalid: true },
136   { prop: "font-variant-ligatures", value: "no-discretionary-ligatures discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
137   { prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures no-common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
139   // font-variant-numeric
140   // valid values
141   { prop: "font-variant-numeric", value: "normal", features: {"lnum": 0, "tnum": 0, "pnum": 0, "onum": 0} },
142   { prop: "font-variant-numeric", value: "lining-nums", features: {"lnum": 1, "onum": 0, "pnum": 0} },
143   { prop: "font-variant-numeric", value: "oldstyle-nums", features: {"lnum": 0, "onum": 1, "pnum": 0} },
144   { prop: "font-variant-numeric", value: "proportional-nums", features: {"lnum": 0, "onum": 0, "pnum": 1, "tnum": 0} },
145   { prop: "font-variant-numeric", value: "proportional-nums oldstyle-nums", features: {"lnum": 0, "onum": 1, "pnum": 1, "tnum": 0} },
146   { prop: "font-variant-numeric", value: "tabular-nums", features: {"tnum": 1, "onum": 0, "pnum": 0} },
147   { prop: "font-variant-numeric", value: "diagonal-fractions", features: {"frac": 1, "afrc": 0, "pnum": 0} },
148   { prop: "font-variant-numeric", value: "stacked-fractions", features: {"frac": 0, "afrc": 1, "pnum": 0} },
149   { prop: "font-variant-numeric", value: "slashed-zero", features: {"zero": 1, "pnum": 0} },
150   { prop: "font-variant-numeric", value: "ordinal", features: {"ordn": 1, "pnum": 0} },
151   { prop: "font-variant-numeric", value: "lining-nums diagonal-fractions", features: {"frac": 1, "afrc": 0, "lnum": 1} },
152   { prop: "font-variant-numeric", value: "tabular-nums stacked-fractions", features: {"frac": 0, "afrc": 1, "tnum": 1} },
153   { prop: "font-variant-numeric", value: "tabular-nums slashed-zero stacked-fractions", features: {"frac": 0, "afrc": 1, "tnum": 1, "zero": 1} },
154   { prop: "font-variant-numeric", value: "proportional-nums slashed-zero diagonal-fractions oldstyle-nums ordinal", features: {"frac": 1, "afrc": 0, "tnum": 0, "pnum": 1, "onum": 1, "ordn": 1, "zero": 1} },
156   // invalid values
157   { prop: "font-variant-numeric", value: "lining-nums normal", features: {"lnum": 0, "onum": 0}, invalid: true },
158   { prop: "font-variant-numeric", value: "lining-nums oldstyle-nums", features: {"lnum": 0, "onum": 0}, invalid: true },
159   { prop: "font-variant-numeric", value: "lining-nums normal slashed-zero ordinal", features: {"lnum": 0, "onum": 0, "zero": 0}, invalid: true },
160   { prop: "font-variant-numeric", value: "proportional-nums tabular-nums", features: {"pnum": 0, "tnum": 0}, invalid: true },
161   { prop: "font-variant-numeric", value: "diagonal-fractions stacked-fractions", features: {"frac": 0, "afrc": 0}, invalid: true },
162   { prop: "font-variant-numeric", value: "slashed-zero diagonal-fractions slashed-zero", features: {"frac": 0, "afrc": 0, "zero": 0}, invalid: true },
163   { prop: "font-variant-numeric", value: "lining-nums slashed-zero diagonal-fractions oldstyle-nums", features: {"frac": 0, "afrc": 0, "zero": 0, "onum": 0}, invalid: true },
165   // font-variant-position
166   // valid values
167   { prop: "font-variant-position", value: "normal", features: {"subs": 0, "sups": 0} },
169   // note: because of fallback, can *only* test activated features here
170   { prop: "font-variant-position", value: "super", features: {"sups": 1} },
171   { prop: "font-variant-position", value: "sub", features: {"subs": 1} },
173   // invalid values
174   { prop: "font-variant-position", value: "super sub", features: {"subs": 0, "sups": 0}, invalid: true },
177 // note: the code below requires an array "gFeatures" from :
178 //   layout/reftests/fonts/gsubtest/gsubtest-features.js
180 // The font defines feature lookups for all OpenType features for a
181 // specific set of PUA codepoints, as listed in the gFeatures array.
182 // Using these codepoints and feature combinations, tests can be
183 // constructed to detect when certain features are enabled or not.
185 // return a created table containing tests for a given property
187 // Ex: { prop: "font-variant-ligatures", value: "common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0} }
189 // This means that for the property 'font-variant-ligatures' with the value 'common-ligatures', the features listed should
190 // either be explicitly enabled or disabled.
192 // propData is the prop/value list with corresponding feature assertions
193 // whichProp is either "all" or a specific subproperty (i.e. "font-variant-position")
194 // isRef is true when this is the reference
195 // debug outputs the prop/value pair along with the tests
197 // default PASS codepoint used for reference rendering
198 // need to use a PUA codepoint to avoid problems related to Freetype auto-hinting
199 const kRefCodepoint = 0xe00c;
201 function createFeatureTestTable(propData, whichProp, isRef, debug)
203   var table = document.createElement("table");
205   if (typeof(isRef) == "undefined") {
206     isRef = false;
207   }
209   if (typeof(debug) == "undefined") {
210     debug = false;
211   }
213   var doAll = (whichProp == "all");
214   for (var i in propData) {
215     var data = propData[i];
217     if (!doAll && data.prop != whichProp) continue;
219     var row = document.createElement("tr");
220     var invalid = false;
221     if ("invalid" in data) {
222       invalid = true;
223       row.className = "invalid";
224     }
226     var cell = document.createElement("td");
227     cell.className = "prop";
228     var styledecl = gPrefix + data.prop + ": " + data.value + ";";
229     cell.innerHTML = styledecl;
230     row.appendChild(cell);
231     if (debug) {
232       table.appendChild(row);
233     }
235     row = document.createElement("tr");
236     if (invalid) {
237       row.className = "invalid";
238     }
240     cell = document.createElement("td");
241     cell.className = "features";
242     if (!isRef) {
243       cell.style.cssText = styledecl;
244     }
246     for (var f in data.features) {
247       var feature = data.features[f];
249       var cp, unsupported = "F".charCodeAt(0);
250       var basecp = gFeatures[f];
252       if (typeof(basecp) == "undefined") {
253         cp = unsupported;
254       } else {
255         switch(feature) {
256         case 0:
257           cp = basecp;
258           break;
259         case 1:
260           cp = basecp + 1;
261           break;
262         case 2:
263           cp = basecp + 2;
264           break;
265         case 3:
266           cp = basecp + 3;
267           break;
268         default:
269           cp = basecp + 1;
270           break;
271         }
272       }
274       var span = document.createElement("span");
275       var cpOut = (isRef ? kRefCodepoint : cp);
276       span.innerHTML = "&#x" + cpOut.toString(16) + ";";
277       span.title = f + "=" + feature;
278       cell.appendChild(span);
279     }
280     row.appendChild(cell);
281     table.appendChild(row);
282   }
284   return table;