|
1 <!DOCTYPE HTML><html> |
|
2 <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=441469 --> |
|
3 <head> |
|
4 <meta http-equiv="content-type" content="text/html; charset=utf-8"> |
|
5 <title>Test of @font-face parser</title> |
|
6 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"> |
|
8 </head> |
|
9 <body> |
|
10 <p>@font-face parsing (<a |
|
11 target="_blank" |
|
12 href="https://bugzilla.mozilla.org/show_bug.cgi?id=441469" |
|
13 >bug 441469</a>)</p> |
|
14 <pre id="display"></pre> |
|
15 <style type="text/css" id="testbox"></style> |
|
16 <script class="testbody" type="text/javascript"> |
|
17 function _(b) { return "@font-face { " + b + " }"; }; |
|
18 var testset = [ |
|
19 // Complete nonsense - shouldn't make a font-face rule at all. |
|
20 { rule: "@font-face;" }, |
|
21 { rule: "font-face { }" }, |
|
22 { rule: "@fontface { }" }, |
|
23 { rule: "@namespace foo url(http://example.com/foo);" }, |
|
24 |
|
25 // Empty rule. |
|
26 { rule: "@font-face { }", d: {} }, |
|
27 { rule: "@font-face {", d: {} }, |
|
28 { rule: "@font-face { ; }", d: {}, noncanonical: true }, |
|
29 |
|
30 // Correct font-family. |
|
31 { rule: _("font-family: \"Mouse\";"), d: {"font-family" : "\"Mouse\""} }, |
|
32 { rule: _("font-family: \"Mouse\""), d: {"font-family" : "\"Mouse\""}, |
|
33 noncanonical: true }, |
|
34 { rule: _("font-family: Mouse;"), d: {"font-family" : "\"Mouse\"" }, |
|
35 noncanonical: true }, |
|
36 { rule: _("font-family: Mouse"), d: {"font-family" : "\"Mouse\"" }, |
|
37 noncanonical: true }, |
|
38 |
|
39 // Correct but unusual font-family. |
|
40 { rule: _("font-family: Hoefler Text;"), |
|
41 d: {"font-family" : "\"Hoefler Text\""}, |
|
42 noncanonical: true }, |
|
43 |
|
44 // Incorrect font-family. |
|
45 { rule: _("font-family:"), d: {} }, |
|
46 { rule: _("font-family \"Mouse\""), d: {} }, |
|
47 { rule: _("font-family: *"), d: {} }, |
|
48 { rule: _("font-family: Mouse, Rat"), d: {} }, |
|
49 { rule: _("font-family: sans-serif"), d: {} }, |
|
50 |
|
51 // Correct font-style. |
|
52 { rule: _("font-style: normal;"), d: {"font-style" : "normal"} }, |
|
53 { rule: _("font-style: italic;"), d: {"font-style" : "italic"} }, |
|
54 { rule: _("font-style: oblique;"), d: {"font-style" : "oblique"} }, |
|
55 |
|
56 // Correct font-weight. |
|
57 { rule: _("font-weight: 100;"), d: {"font-weight" : "100"} }, |
|
58 { rule: _("font-weight: 200;"), d: {"font-weight" : "200"} }, |
|
59 { rule: _("font-weight: 300;"), d: {"font-weight" : "300"} }, |
|
60 { rule: _("font-weight: 400;"), d: {"font-weight" : "400"} }, |
|
61 { rule: _("font-weight: 500;"), d: {"font-weight" : "500"} }, |
|
62 { rule: _("font-weight: 600;"), d: {"font-weight" : "600"} }, |
|
63 { rule: _("font-weight: 700;"), d: {"font-weight" : "700"} }, |
|
64 { rule: _("font-weight: 800;"), d: {"font-weight" : "800"} }, |
|
65 { rule: _("font-weight: 900;"), d: {"font-weight" : "900"} }, |
|
66 { rule: _("font-weight: normal;"), d: {"font-weight" : "normal"} }, |
|
67 { rule: _("font-weight: bold;"), d: {"font-weight" : "bold"} }, |
|
68 |
|
69 // Incorrect font-weight. |
|
70 { rule: _("font-weight: bolder;"), d: {} }, |
|
71 { rule: _("font-weight: lighter;"), d: {} }, |
|
72 |
|
73 // Correct font-stretch. |
|
74 { rule: _("font-stretch: ultra-condensed;"), |
|
75 d: {"font-stretch" : "ultra-condensed"} }, |
|
76 { rule: _("font-stretch: extra-condensed;"), |
|
77 d: {"font-stretch" : "extra-condensed"} }, |
|
78 { rule: _("font-stretch: condensed;"), |
|
79 d: {"font-stretch" : "condensed"} }, |
|
80 { rule: _("font-stretch: semi-condensed;"), |
|
81 d: {"font-stretch" : "semi-condensed"} }, |
|
82 { rule: _("font-stretch: normal;"), |
|
83 d: {"font-stretch" : "normal"} }, |
|
84 { rule: _("font-stretch: semi-expanded;"), |
|
85 d: {"font-stretch" : "semi-expanded"} }, |
|
86 { rule: _("font-stretch: expanded;"), |
|
87 d: {"font-stretch" : "expanded"} }, |
|
88 { rule: _("font-stretch: extra-expanded;"), |
|
89 d: {"font-stretch" : "extra-expanded"} }, |
|
90 { rule: _("font-stretch: ultra-expanded;"), |
|
91 d: {"font-stretch" : "ultra-expanded"} }, |
|
92 |
|
93 // Incorrect font-stretch. |
|
94 { rule: _("font-stretch: wider;"), d: {} }, |
|
95 { rule: _("font-stretch: narrower;"), d: {} }, |
|
96 |
|
97 // Correct src: |
|
98 { rule: _("src: url(\"/fonts/Mouse\");"), |
|
99 d: { "src" : "url(\"/fonts/Mouse\")" } }, |
|
100 { rule: _("src: url(/fonts/Mouse);"), |
|
101 d: { "src" : "url(\"/fonts/Mouse\")" }, noncanonical: true }, |
|
102 |
|
103 { rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\");"), |
|
104 d: { "src" : "url(\"/fonts/Mouse\") format(\"truetype\")" } }, |
|
105 { rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\", \"opentype\");"), |
|
106 d: { "src" : "url(\"/fonts/Mouse\") format(\"truetype\", \"opentype\")" } }, |
|
107 |
|
108 { rule: _("src: url(\"/fonts/Mouse\"), url(\"/fonts/Rat\");"), |
|
109 d: { "src" : "url(\"/fonts/Mouse\"), url(\"/fonts/Rat\")" } }, |
|
110 |
|
111 { rule: _("src: local(Mouse), url(\"/fonts/Mouse\");"), |
|
112 d: { "src" : "local(\"Mouse\"), url(\"/fonts/Mouse\")" }, |
|
113 noncanonical: true }, |
|
114 |
|
115 { rule: _("src: local(\"老鼠\"), url(\"/fonts/Mouse\");"), |
|
116 d: { "src" : "local(\"老鼠\"), url(\"/fonts/Mouse\")" } }, |
|
117 |
|
118 { rule: _("src: local(\"老鼠\"), url(\"/fonts/Mouse\") format(\"truetype\");"), |
|
119 d: { "src" : "local(\"老鼠\"), url(\"/fonts/Mouse\") format(\"truetype\")" } }, |
|
120 |
|
121 // Correct but unusual src: |
|
122 { rule: _("src: local(Hoefler Text);"), |
|
123 d: {"src" : "local(\"Hoefler Text\")"}, noncanonical: true }, |
|
124 |
|
125 // Incorrect src: |
|
126 { rule: _("src:"), d: {} }, |
|
127 { rule: _("src: \"/fonts/Mouse\";"), d: {} }, |
|
128 { rule: _("src: /fonts/Mouse;"), d: {} }, |
|
129 { rule: _("src: url(\"/fonts/Mouse\") format(truetype);"), d: {} }, |
|
130 { rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\",opentype);"), d: {} }, |
|
131 { rule: _("src: local(*);"), d: {} }, |
|
132 { rule: _("src: format(\"truetype\");"), d: {} }, |
|
133 { rule: _("src: local(Mouse) format(\"truetype\");"), d: {} }, |
|
134 { rule: _("src: local(Mouse, Rat);"), d: {} }, |
|
135 { rule: _("src: local(sans-serif);"), d: {} }, |
|
136 |
|
137 // Repeated descriptors |
|
138 { rule: _("font-weight: 700; font-weight: 200;"), |
|
139 d: {"font-weight" : "200"}, |
|
140 noncanonical: true }, |
|
141 { rule: _("src: url(\"/fonts/Cat\"); src: url(\"/fonts/Mouse\");"), |
|
142 d: { "src" : "url(\"/fonts/Mouse\")" }, |
|
143 noncanonical: true }, |
|
144 { rule: _("src: local(Cat); src: local(Mouse)"), |
|
145 d: { "src" : "local(\"Mouse\")" }, |
|
146 noncanonical: true }, |
|
147 |
|
148 // Correct parenthesis matching for local() |
|
149 { rule: _("src: local(Mouse); src: local(Cat(); src: local(Rat); )"), |
|
150 d: { "src" : "local(\"Mouse\")" }, |
|
151 noncanonical: true }, |
|
152 { rule: _("src: local(Mouse); src: local(\"Cat\"; src: local(Rat); )"), |
|
153 d: { "src" : "local(\"Mouse\")" }, |
|
154 noncanonical: true }, |
|
155 |
|
156 // Correct parenthesis matching for format() |
|
157 { rule: _("src: url(\"/fonts/Mouse\"); " + |
|
158 "src: url(\"/fonts/Cat\") format(Cat(); src: local(Rat); )"), |
|
159 d: { "src" : "url(\"/fonts/Mouse\")" }, |
|
160 noncanonical: true }, |
|
161 { rule: _("src: url(\"/fonts/Mouse\"); " + |
|
162 "src: url(\"/fonts/Cat\") format(\"Cat\"; src: local(Rat); )"), |
|
163 d: { "src" : "url(\"/fonts/Mouse\")" }, |
|
164 noncanonical: true }, |
|
165 { rule: _("src: url(\"/fonts/Mouse\"); " + |
|
166 "src: url(\"/fonts/Cat\") format((); src: local(Rat); )"), |
|
167 d: { "src" : "url(\"/fonts/Mouse\")" }, |
|
168 noncanonical: true }, |
|
169 |
|
170 // Correct unicode-range: |
|
171 { rule: _("unicode-range: U+00A5;"), d: { "unicode-range" : "U+00A5" } }, |
|
172 { rule: _("unicode-range: U+A5;"), |
|
173 d: { "unicode-range" : "U+00A5" }, noncanonical: true }, |
|
174 { rule: _("unicode-range: U+00a5;"), |
|
175 d: { "unicode-range" : "U+00A5" }, noncanonical: true }, |
|
176 { rule: _("unicode-range: u+00a5;"), |
|
177 d: { "unicode-range" : "U+00A5" }, noncanonical: true }, |
|
178 { rule: _("unicode-range: U+0000-00FF;"), |
|
179 d: { "unicode-range" : "U+0000-00FF" } }, |
|
180 { rule: _("unicode-range: U+00??;"), |
|
181 d: { "unicode-range" : "U+0000-00FF" }, noncanonical: true }, |
|
182 { rule: _("unicode-range: U+?"), |
|
183 d: { "unicode-range" : "U+0000-000F" }, noncanonical: true }, |
|
184 { rule: _("unicode-range: U+??????"), |
|
185 d: { "unicode-range" : "U+0000-10FFFF" }, noncanonical: true }, |
|
186 { rule: _("unicode-range: U+590-5ff;"), |
|
187 d: { "unicode-range" : "U+0590-05FF" }, noncanonical: true }, |
|
188 { rule: _("unicode-range: U+A0000-12FFFF"), |
|
189 d: { "unicode-range" : "U+A0000-10FFFF" }, noncanonical: true }, |
|
190 |
|
191 { rule: _("unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;"), |
|
192 d: { "unicode-range" : "U+00A5, U+4E00-9FFF, U+3000-30FF, U+FF00-FF9F" }, |
|
193 noncanonical: true }, |
|
194 |
|
195 { rule: _("unicode-range: U+104??;"), |
|
196 d: { "unicode-range" : "U+10400-104FF" }, noncanonical: true }, |
|
197 { rule: _("unicode-range: U+320??, U+321??, U+322??, U+323??, U+324??, U+325??;"), |
|
198 d: { "unicode-range" : "U+32000-320FF, U+32100-321FF, U+32200-322FF, U+32300-323FF, U+32400-324FF, U+32500-325FF" }, |
|
199 noncanonical: true }, |
|
200 { rule: _("unicode-range: U+100000-10ABCD;"), |
|
201 d: { "unicode-range" : "U+100000-10ABCD" } }, |
|
202 { rule: _("unicode-range: U+0121 , U+1023"), |
|
203 d: { "unicode-range" : "U+0121, U+1023" }, noncanonical: true }, |
|
204 { rule: _("unicode-range: U+0121/**/, U+1023"), |
|
205 d: { "unicode-range" : "U+0121, U+1023" }, noncanonical: true }, |
|
206 |
|
207 // Incorrect unicode-range: |
|
208 { rule: _("unicode-range:"), d: {} }, |
|
209 { rule: _("unicode-range: U+"), d: {} }, |
|
210 { rule: _("unicode-range: U+8FFFFFFF"), d: {} }, |
|
211 { rule: _("unicode-range: U+8FFF-7000"), d: {} }, |
|
212 { rule: _("unicode-range: U+8F??-9000"), d: {} }, |
|
213 { rule: _("unicode-range: U+9000-9???"), d: {} }, |
|
214 { rule: _("unicode-range: U+??00"), d: {} }, |
|
215 { rule: _("unicode-range: U+12345678?"), d: {} }, |
|
216 { rule: _("unicode-range: U+1????????"), d: {} }, |
|
217 { rule: _("unicode-range: twelve"), d: {} }, |
|
218 { rule: _("unicode-range: 1000"), d: {} }, |
|
219 { rule: _("unicode-range: 13??"), d: {} }, |
|
220 { rule: _("unicode-range: 1300-1377"), d: {} }, |
|
221 { rule: _("unicode-range: U-1000"), d: {} }, |
|
222 { rule: _("unicode-range: U+nnnn"), d: {} }, |
|
223 { rule: _("unicode-range: U+0121 U+1023"), d: {} }, |
|
224 { rule: _("unicode-range: U+ 0121"), d: {} }, |
|
225 { rule: _("unicode-range: U +0121"), d: {} }, |
|
226 { rule: _("unicode-range: U+0121-"), d: {} }, |
|
227 { rule: _("unicode-range: U+0121- 1023"), d: {} }, |
|
228 { rule: _("unicode-range: U+0121 -1023"), d: {} }, |
|
229 { rule: _("unicode-range: U+012 ?"), d: {} }, |
|
230 { rule: _("unicode-range: U+01 2?"), d: {} }, |
|
231 |
|
232 // Thorough test of seven-digit rejection: all these are syntax errors |
|
233 { rule: _("unicode-range: U+1034560, U+A5"), d: {} }, |
|
234 { rule: _("unicode-range: U+1034569, U+A5"), d: {} }, |
|
235 { rule: _("unicode-range: U+103456a, U+A5"), d: {} }, |
|
236 { rule: _("unicode-range: U+103456f, U+A5"), d: {} }, |
|
237 { rule: _("unicode-range: U+103456?, U+A5"), d: {} }, |
|
238 { rule: _("unicode-range: U+103456-1034560, U+A5"), d: {} }, |
|
239 { rule: _("unicode-range: U+103456-1034569, U+A5"), d: {} }, |
|
240 { rule: _("unicode-range: U+103456-103456a, U+A5"), d: {} }, |
|
241 { rule: _("unicode-range: U+103456-103456f, U+A5"), d: {} }, |
|
242 |
|
243 // Syntactically invalid unicode-range tokens invalidate the |
|
244 // entire descriptor |
|
245 { rule: _("unicode-range: U+1, U+2, U+X"), d: {} }, |
|
246 { rule: _("unicode-range: U+A5, U+0?F"), d: {} }, |
|
247 { rule: _("unicode-range: U+A5, U+0F?-E00"), d: {} }, |
|
248 |
|
249 // Descending ranges and ranges outside 0-10FFFF are ignored |
|
250 // but do not invalidate the descriptor |
|
251 { rule: _("unicode-range: U+A5, U+90-30"), |
|
252 d: { "unicode-range" : "U+00A5" }, noncanonical: true }, |
|
253 { rule: _("unicode-range: U+A5, U+220043"), |
|
254 d: { "unicode-range" : "U+00A5" }, noncanonical: true }, |
|
255 |
|
256 // -moz-font-feature-settings |
|
257 { rule: _("-moz-font-feature-settings: normal;"), |
|
258 d: { "-moz-font-feature-settings" : "normal" } }, |
|
259 { rule: _("-moz-font-feature-settings: \"dlig\";"), |
|
260 d: { "-moz-font-feature-settings" : "\"dlig\"" } }, |
|
261 { rule: _("-moz-font-feature-settings: \"dlig\" 1;"), |
|
262 d: { "-moz-font-feature-settings" : "\"dlig\"" }, noncanonical: true }, |
|
263 { rule: _("-moz-font-feature-settings: 'dlig' 1"), |
|
264 d: { "-moz-font-feature-settings" : "\"dlig\"" }, noncanonical: true }, |
|
265 |
|
266 // incorrect -moz-font-feature-settings |
|
267 { rule: _("-moz-font-feature-settings: dlig 1"), d: {} }, |
|
268 { rule: _("-moz-font-feature-settings: none;"), d: {} }, |
|
269 { rule: _("-moz-font-feature-settings: 0;"), d: {} }, |
|
270 { rule: _("-moz-font-feature-settings: 3.14;"), d: {} }, |
|
271 { rule: _("-moz-font-feature-settings: 'blah' 3.14;"), d: {} }, |
|
272 { rule: _("-moz-font-feature-settings: 'dlig' 1 'hist' 0;"), d: {} }, |
|
273 { rule: _("-moz-font-feature-settings: 'dlig=1,hist=1'"), d: {} }, |
|
274 |
|
275 // -moz-font-language-override: |
|
276 { rule: _("-moz-font-language-override: normal;"), |
|
277 d: { "-moz-font-language-override" : "normal" } }, |
|
278 { rule: _("-moz-font-language-override: \"TRK\";"), |
|
279 d: { "-moz-font-language-override" : "\"TRK\"" } }, |
|
280 { rule: _("-moz-font-language-override: 'TRK'"), |
|
281 d: { "-moz-font-language-override" : "\"TRK\"" }, noncanonical: true }, |
|
282 |
|
283 // incorrect -moz-font-language-override |
|
284 { rule: _("-moz-font-language-override: TRK"), d: {} }, |
|
285 { rule: _("-moz-font-language-override: none;"), d: {} }, |
|
286 { rule: _("-moz-font-language-override: 0;"), d: {} }, |
|
287 { rule: _("-moz-font-language-override: #999;"), d: {} }, |
|
288 { rule: _("-moz-font-language-override: 'TRK' 'SRB'"), d: {} }, |
|
289 { rule: _("-moz-font-language-override: 'TRK', 'SRB'"), d: {} }, |
|
290 ]; |
|
291 |
|
292 var display = document.getElementById("display"); |
|
293 var sheet = document.styleSheets[1]; |
|
294 |
|
295 for (var curTest = 0; curTest < testset.length; curTest++) { |
|
296 try { |
|
297 while(sheet.cssRules.length > 0) |
|
298 sheet.deleteRule(0); |
|
299 sheet.insertRule(testset[curTest].rule, 0); |
|
300 } catch (e) { |
|
301 ok(e.name == "SyntaxError" |
|
302 && e instanceof DOMException |
|
303 && e.code == DOMException.SYNTAX_ERR |
|
304 && !('d' in testset[curTest]), |
|
305 testset[curTest].rule + " syntax error thrown", e); |
|
306 } |
|
307 |
|
308 try { |
|
309 if (testset[curTest].d) { |
|
310 is(sheet.cssRules.length, 1, |
|
311 testset[curTest].rule + " rule count"); |
|
312 is(sheet.cssRules[0].type, 5 /*FONT_FACE_RULE*/, |
|
313 testset[curTest].rule + " rule type"); |
|
314 |
|
315 var d = testset[curTest].d; |
|
316 var s = sheet.cssRules[0].style; |
|
317 var n = 0; |
|
318 |
|
319 // everything is set that should be |
|
320 for (var name in d) { |
|
321 is(s.getPropertyValue(name), d[name], |
|
322 testset[curTest].rule + " (prop " + name + ")"); |
|
323 n++; |
|
324 } |
|
325 // nothing else is set |
|
326 is(s.length, n, testset[curTest].rule + "prop count"); |
|
327 for (var i = 0; i < s.length; i++) { |
|
328 ok(s[i] in d, testset[curTest].rule, |
|
329 "Unexpected item #" + i + ": " + s[i]); |
|
330 } |
|
331 |
|
332 // round-tripping of cssText |
|
333 // this is a strong test; it's okay if the exact serialization |
|
334 // changes in the future |
|
335 if (n && !testset[curTest].noncanonical) { |
|
336 is(sheet.cssRules[0].cssText.replace(/[ \n]+/g, " "), |
|
337 testset[curTest].rule, |
|
338 testset[curTest].rule + " rule text"); |
|
339 } |
|
340 } else { |
|
341 if (sheet.cssRules.length == 0) { |
|
342 is(sheet.cssRules.length, 0, |
|
343 testset[curTest].rule + " rule count (0)"); |
|
344 } else { |
|
345 is(sheet.cssRules.length, 1, |
|
346 testset[curTest].rule + " rule count (1 non-fontface)"); |
|
347 isnot(sheet.cssRules[0].type, 5 /*FONT_FACE_RULE*/, |
|
348 testset[curTest].rule + " rule type (1 non-fontface)"); |
|
349 } |
|
350 } |
|
351 } catch (e) { |
|
352 ok(false, testset[curTest].rule, "During test: " + e); |
|
353 } |
|
354 } |
|
355 </script> |
|
356 </body> |
|
357 </html> |