Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | <html xmlns="http://www.w3.org/1999/xhtml"> |
michael@0 | 2 | <head> |
michael@0 | 3 | <title>Test for SMIL keyTimes</title> |
michael@0 | 4 | <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 5 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
michael@0 | 6 | </head> |
michael@0 | 7 | <body> |
michael@0 | 8 | <a target="_blank" |
michael@0 | 9 | href="https://bugzilla.mozilla.org/show_bug.cgi?id=557885">Mozilla Bug |
michael@0 | 10 | 557885</a> |
michael@0 | 11 | <p id="display"></p> |
michael@0 | 12 | <div id="content" style="display: none"> |
michael@0 | 13 | <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px"> |
michael@0 | 14 | <circle cx="-100" cy="20" r="15" fill="blue" id="circle"/> |
michael@0 | 15 | </svg> |
michael@0 | 16 | </div> |
michael@0 | 17 | <pre id="test"> |
michael@0 | 18 | <script class="testbody" type="text/javascript"> |
michael@0 | 19 | <![CDATA[ |
michael@0 | 20 | /** Test for SMIL keyTimes **/ |
michael@0 | 21 | |
michael@0 | 22 | var gSvg = document.getElementById("svg"); |
michael@0 | 23 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 24 | |
michael@0 | 25 | function main() |
michael@0 | 26 | { |
michael@0 | 27 | gSvg.pauseAnimations(); |
michael@0 | 28 | |
michael@0 | 29 | var testCases = Array(); |
michael@0 | 30 | |
michael@0 | 31 | // Simple case |
michael@0 | 32 | testCases.push({ |
michael@0 | 33 | 'attr' : { 'values': '0; 50; 100', |
michael@0 | 34 | 'keyTimes': '0; .8; 1' }, |
michael@0 | 35 | 'times': [ [ 4, 25 ], |
michael@0 | 36 | [ 8, 50 ], |
michael@0 | 37 | [ 9, 75 ], |
michael@0 | 38 | [ 10, 100 ] ] |
michael@0 | 39 | }); |
michael@0 | 40 | |
michael@0 | 41 | // Parsing tests |
michael@0 | 42 | testCases.push(parseOk(' 0 ; .8;1 ')); // extra whitespace |
michael@0 | 43 | testCases.push(parseNotOk(';0; .8; 1')); // leading semi-colon |
michael@0 | 44 | testCases.push(parseNotOk('; .8; 1')); // leading semi-colon |
michael@0 | 45 | testCases.push(parseOk('0; .8; 1;')); // trailing semi-colon |
michael@0 | 46 | testCases.push(parseNotOk('')); // empty string |
michael@0 | 47 | testCases.push(parseNotOk(' ')); // empty string |
michael@0 | 48 | testCases.push(parseNotOk('0; .8')); // too few values |
michael@0 | 49 | testCases.push(parseNotOk('0; .8; .9; 1')); // too many values |
michael@0 | 50 | testCases.push(parseNotOk('0; 1; .8')); // non-increasing |
michael@0 | 51 | testCases.push(parseNotOk('0; .8; .9')); // final value non-1 with |
michael@0 | 52 | // calcMode=linear |
michael@0 | 53 | testCases.push(parseOk('0; .8; .9', { 'calcMode': 'discrete' })); |
michael@0 | 54 | testCases.push(parseNotOk('0.01; .8; 1')); // first value not 0 |
michael@0 | 55 | testCases.push(parseNotOk('0.01; .8; 1', { 'calcMode': 'discrete' })); |
michael@0 | 56 | // first value not 0 |
michael@0 | 57 | testCases.push(parseNotOk('0; .8; 1.1')); // out of range |
michael@0 | 58 | testCases.push(parseNotOk('-0.1; .8; 1')); // out of range |
michael@0 | 59 | |
michael@0 | 60 | |
michael@0 | 61 | // 2 values |
michael@0 | 62 | testCases.push({ |
michael@0 | 63 | 'attr' : { 'values': '0; 50', |
michael@0 | 64 | 'keyTimes': '0; 1' }, |
michael@0 | 65 | 'times': [ [ 6, 30 ] ] |
michael@0 | 66 | }); |
michael@0 | 67 | |
michael@0 | 68 | // 1 value |
michael@0 | 69 | testCases.push({ |
michael@0 | 70 | 'attr' : { 'values': '50', |
michael@0 | 71 | 'keyTimes': ' 0' }, |
michael@0 | 72 | 'times': [ [ 7, 50 ] ] |
michael@0 | 73 | }); |
michael@0 | 74 | |
michael@0 | 75 | // 1 bad value |
michael@0 | 76 | testCases.push({ |
michael@0 | 77 | 'attr' : { 'values': '50', |
michael@0 | 78 | 'keyTimes': '0.1' }, |
michael@0 | 79 | 'times': [ [ 0, -100 ] ] |
michael@0 | 80 | }); |
michael@0 | 81 | |
michael@0 | 82 | // 1 value, calcMode=discrete |
michael@0 | 83 | testCases.push({ |
michael@0 | 84 | 'attr' : { 'values': '50', |
michael@0 | 85 | 'calcMode': 'discrete', |
michael@0 | 86 | 'keyTimes': ' 0' }, |
michael@0 | 87 | 'times': [ [ 7, 50 ] ] |
michael@0 | 88 | }); |
michael@0 | 89 | |
michael@0 | 90 | // 1 bad value, calcMode=discrete |
michael@0 | 91 | testCases.push({ |
michael@0 | 92 | 'attr' : { 'values': '50', |
michael@0 | 93 | 'calcMode': 'discrete', |
michael@0 | 94 | 'keyTimes': '0.1' }, |
michael@0 | 95 | 'times': [ [ 0, -100 ] ] |
michael@0 | 96 | }); |
michael@0 | 97 | |
michael@0 | 98 | // from-to |
michael@0 | 99 | testCases.push({ |
michael@0 | 100 | 'attr' : { 'from': '10', |
michael@0 | 101 | 'to': '20', |
michael@0 | 102 | 'keyTimes': '0.0; 1.0' }, |
michael@0 | 103 | 'times': [ [ 3.5, 13.5 ] ] |
michael@0 | 104 | }); |
michael@0 | 105 | |
michael@0 | 106 | // from-to calcMode=discrete |
michael@0 | 107 | testCases.push({ |
michael@0 | 108 | 'attr' : { 'from': '10', |
michael@0 | 109 | 'to': '20', |
michael@0 | 110 | 'calcMode': 'discrete', |
michael@0 | 111 | 'keyTimes': '0.0; 0.7' }, |
michael@0 | 112 | 'times': [ [ 0, 10 ], |
michael@0 | 113 | [ 6.9, 10 ], |
michael@0 | 114 | [ 7.0, 20 ], |
michael@0 | 115 | [ 10.0, 20 ], |
michael@0 | 116 | [ 11.0, 20 ] ] |
michael@0 | 117 | }); |
michael@0 | 118 | |
michael@0 | 119 | // from-to calcMode=discrete one keyTime only |
michael@0 | 120 | testCases.push({ |
michael@0 | 121 | 'attr' : { 'values': '20', |
michael@0 | 122 | 'calcMode': 'discrete', |
michael@0 | 123 | 'keyTimes': '0' }, |
michael@0 | 124 | 'times': [ [ 0, 20 ], |
michael@0 | 125 | [ 6.9, 20 ], |
michael@0 | 126 | [ 7.0, 20 ], |
michael@0 | 127 | [ 10.0, 20 ], |
michael@0 | 128 | [ 11.0, 20 ] ] |
michael@0 | 129 | }); |
michael@0 | 130 | |
michael@0 | 131 | // from-to calcMode=discrete one keyTime, mismatches no. values |
michael@0 | 132 | testCases.push({ |
michael@0 | 133 | 'attr' : { 'values': '10; 20', |
michael@0 | 134 | 'calcMode': 'discrete', |
michael@0 | 135 | 'keyTimes': '0' }, |
michael@0 | 136 | 'times': [ [ 0, -100 ] ] |
michael@0 | 137 | }); |
michael@0 | 138 | |
michael@0 | 139 | // to |
michael@0 | 140 | testCases.push({ |
michael@0 | 141 | 'attr' : { 'to': '100', |
michael@0 | 142 | 'keyTimes': '0.0; 1.0' }, |
michael@0 | 143 | 'times': [ [ 0, -100 ], |
michael@0 | 144 | [ 7, 40 ] ] |
michael@0 | 145 | }); |
michael@0 | 146 | |
michael@0 | 147 | // to -- bad number of keyTimes (too many) |
michael@0 | 148 | testCases.push({ |
michael@0 | 149 | 'attr' : { 'to': '100', |
michael@0 | 150 | 'keyTimes': '0.0; 0.5; 1.0' }, |
michael@0 | 151 | 'times': [ [ 2, -100 ] ] |
michael@0 | 152 | }); |
michael@0 | 153 | |
michael@0 | 154 | // unfrozen to calcMode=discrete two keyTimes |
michael@0 | 155 | testCases.push({ |
michael@0 | 156 | 'attr' : { 'to': '100', |
michael@0 | 157 | 'calcMode': 'discrete', |
michael@0 | 158 | 'keyTimes': '0.0; 1.0', |
michael@0 | 159 | 'fill': 'remove' }, |
michael@0 | 160 | 'times': [ [ 0, -100 ], |
michael@0 | 161 | [ 7, -100 ], |
michael@0 | 162 | [ 10, -100 ], |
michael@0 | 163 | [ 12, -100 ]] |
michael@0 | 164 | }); |
michael@0 | 165 | |
michael@0 | 166 | // frozen to calcMode=discrete two keyTimes |
michael@0 | 167 | testCases.push({ |
michael@0 | 168 | 'attr' : { 'to': '100', |
michael@0 | 169 | 'calcMode': 'discrete', |
michael@0 | 170 | 'keyTimes': '0.0; 1.0' }, |
michael@0 | 171 | 'times': [ [ 0, -100 ], |
michael@0 | 172 | [ 7, -100 ], |
michael@0 | 173 | [ 10, 100 ], |
michael@0 | 174 | [ 12, 100 ] ] |
michael@0 | 175 | }); |
michael@0 | 176 | |
michael@0 | 177 | // to calcMode=discrete -- bad number of keyTimes (one, expecting two) |
michael@0 | 178 | testCases.push({ |
michael@0 | 179 | 'attr' : { 'to': '100', |
michael@0 | 180 | 'calcMode': 'discrete', |
michael@0 | 181 | 'keyTimes': '0' }, |
michael@0 | 182 | 'times': [ [ 0, -100 ], |
michael@0 | 183 | [ 7, -100 ] ] |
michael@0 | 184 | }); |
michael@0 | 185 | |
michael@0 | 186 | // values calcMode=discrete |
michael@0 | 187 | testCases.push({ |
michael@0 | 188 | 'attr' : { 'values': '0; 10; 20; 30', |
michael@0 | 189 | 'calcMode': 'discrete', |
michael@0 | 190 | 'keyTimes': '0;.2;.4;.6' }, |
michael@0 | 191 | 'times': [ [ 0, 0 ], |
michael@0 | 192 | [ 1.9, 0 ], |
michael@0 | 193 | [ 2, 10 ], |
michael@0 | 194 | [ 3.9, 10 ], |
michael@0 | 195 | [ 4.0, 20 ], |
michael@0 | 196 | [ 5.9, 20 ], |
michael@0 | 197 | [ 6.0, 30 ], |
michael@0 | 198 | [ 9.9, 30 ], |
michael@0 | 199 | [ 10.0, 30 ] ] |
michael@0 | 200 | }); |
michael@0 | 201 | |
michael@0 | 202 | // The following two accumulate tests are from SMIL 3.0 |
michael@0 | 203 | // (Note that this behaviour differs from that defined for SVG Tiny 1.2 which |
michael@0 | 204 | // specifically excludes the last value: "Note that in the case of discrete |
michael@0 | 205 | // animation, the frozen value that is used is the value of the animation just |
michael@0 | 206 | // before the end of the active duration.") |
michael@0 | 207 | // accumulate=none |
michael@0 | 208 | testCases.push({ |
michael@0 | 209 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 210 | 'calcMode': 'discrete', |
michael@0 | 211 | 'keyTimes': '0;.5;1', |
michael@0 | 212 | 'fill': 'freeze', |
michael@0 | 213 | 'repeatCount': '2', |
michael@0 | 214 | 'accumulate': 'none' }, |
michael@0 | 215 | 'times': [ [ 0, 0 ], |
michael@0 | 216 | [ 5, 10 ], |
michael@0 | 217 | [ 10, 0 ], |
michael@0 | 218 | [ 15, 10 ], |
michael@0 | 219 | [ 20, 20 ], |
michael@0 | 220 | [ 25, 20 ] ] |
michael@0 | 221 | }); |
michael@0 | 222 | |
michael@0 | 223 | // accumulate=sum |
michael@0 | 224 | testCases.push({ |
michael@0 | 225 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 226 | 'calcMode': 'discrete', |
michael@0 | 227 | 'keyTimes': '0;.5;1', |
michael@0 | 228 | 'fill': 'freeze', |
michael@0 | 229 | 'repeatCount': '2', |
michael@0 | 230 | 'accumulate': 'sum' }, |
michael@0 | 231 | 'times': [ [ 0, 0 ], |
michael@0 | 232 | [ 5, 10 ], |
michael@0 | 233 | [ 10, 20 ], |
michael@0 | 234 | [ 15, 30 ], |
michael@0 | 235 | [ 20, 40 ], |
michael@0 | 236 | [ 25, 40 ] ] |
michael@0 | 237 | }); |
michael@0 | 238 | |
michael@0 | 239 | // If the interpolation mode is paced, the keyTimes attribute is ignored. |
michael@0 | 240 | testCases.push({ |
michael@0 | 241 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 242 | 'calcMode': 'paced', |
michael@0 | 243 | 'keyTimes': '0;.2;1' }, |
michael@0 | 244 | 'times': [ [ 0, 0 ], |
michael@0 | 245 | [ 2, 4 ], |
michael@0 | 246 | [ 5, 10 ] ] |
michael@0 | 247 | }); |
michael@0 | 248 | |
michael@0 | 249 | // SMIL 3 has: |
michael@0 | 250 | // If the simple duration is indefinite and the interpolation mode is |
michael@0 | 251 | // linear or spline, any keyTimes specification will be ignored. |
michael@0 | 252 | // However, since keyTimes represent "a proportional offset into the simple |
michael@0 | 253 | // duration of the animation element" surely discrete animation too cannot use |
michael@0 | 254 | // keyTimes when the simple duration is indefinite. Hence SVGT 1.2 is surely |
michael@0 | 255 | // more correct when it has: |
michael@0 | 256 | // If the simple duration is indefinite, any 'keyTimes' specification will |
michael@0 | 257 | // be ignored. |
michael@0 | 258 | // (linear) |
michael@0 | 259 | testCases.push({ |
michael@0 | 260 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 261 | 'dur': 'indefinite', |
michael@0 | 262 | 'keyTimes': '0;.2;1' }, |
michael@0 | 263 | 'times': [ [ 0, 0 ], |
michael@0 | 264 | [ 5, 0 ] ] |
michael@0 | 265 | }); |
michael@0 | 266 | // (spline) |
michael@0 | 267 | testCases.push({ |
michael@0 | 268 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 269 | 'dur': 'indefinite', |
michael@0 | 270 | 'calcMode': 'spline', |
michael@0 | 271 | 'keyTimes': '0;.2;1', |
michael@0 | 272 | 'keySplines': '0 0 1 1; 0 0 1 1' }, |
michael@0 | 273 | 'times': [ [ 0, 0 ], |
michael@0 | 274 | [ 5, 0 ] ] |
michael@0 | 275 | }); |
michael@0 | 276 | // (discrete) |
michael@0 | 277 | testCases.push({ |
michael@0 | 278 | 'attr' : { 'values': '0; 10; 20', |
michael@0 | 279 | 'dur': 'indefinite', |
michael@0 | 280 | 'calcMode': 'discrete', |
michael@0 | 281 | 'keyTimes': '0;.2;1' }, |
michael@0 | 282 | 'times': [ [ 0, 0 ], |
michael@0 | 283 | [ 5, 0 ] ] |
michael@0 | 284 | }); |
michael@0 | 285 | |
michael@0 | 286 | for (var i = 0; i < testCases.length; i++) { |
michael@0 | 287 | gSvg.setCurrentTime(0); |
michael@0 | 288 | var test = testCases[i]; |
michael@0 | 289 | |
michael@0 | 290 | // Create animation elements |
michael@0 | 291 | var anim = createAnim(test.attr); |
michael@0 | 292 | |
michael@0 | 293 | // Run samples |
michael@0 | 294 | for (var j = 0; j < test.times.length; j++) { |
michael@0 | 295 | var times = test.times[j]; |
michael@0 | 296 | gSvg.setCurrentTime(times[0]); |
michael@0 | 297 | checkSample(anim, times[1], times[0], i); |
michael@0 | 298 | } |
michael@0 | 299 | |
michael@0 | 300 | anim.parentNode.removeChild(anim); |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | // fallback to discrete for non-additive animation |
michael@0 | 304 | var attr = { 'values': 'butt; round; square', |
michael@0 | 305 | 'attributeName': 'stroke-linecap', |
michael@0 | 306 | 'calcMode': 'linear', |
michael@0 | 307 | 'keyTimes': '0;.2;1', |
michael@0 | 308 | 'fill': 'remove' }; |
michael@0 | 309 | var anim = createAnim(attr); |
michael@0 | 310 | var samples = [ [ 0, 'butt' ], |
michael@0 | 311 | [ 1.9, 'butt' ], |
michael@0 | 312 | [ 2.0, 'round' ], |
michael@0 | 313 | [ 9.9, 'round' ], |
michael@0 | 314 | [ 10, 'butt' ] // fill=remove so we'll never set it to square |
michael@0 | 315 | ]; |
michael@0 | 316 | for (var i = 0; i < samples.length; i++) { |
michael@0 | 317 | var sample = samples[i]; |
michael@0 | 318 | gSvg.setCurrentTime(sample[0]); |
michael@0 | 319 | checkLineCapSample(anim, sample[1], sample[0], |
michael@0 | 320 | "[non-interpolatable fallback]"); |
michael@0 | 321 | } |
michael@0 | 322 | anim.parentNode.removeChild(anim); |
michael@0 | 323 | |
michael@0 | 324 | SimpleTest.finish(); |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | function parseOk(str, extra) |
michael@0 | 328 | { |
michael@0 | 329 | var attr = { 'values': '0; 50; 100', |
michael@0 | 330 | 'keyTimes': str }; |
michael@0 | 331 | if (typeof(extra) == "object") { |
michael@0 | 332 | for (name in extra) { |
michael@0 | 333 | attr[name] = extra[name]; |
michael@0 | 334 | } |
michael@0 | 335 | } |
michael@0 | 336 | return { |
michael@0 | 337 | 'attr' : attr, |
michael@0 | 338 | 'times': [ [ 0, 0 ] ] |
michael@0 | 339 | }; |
michael@0 | 340 | } |
michael@0 | 341 | |
michael@0 | 342 | function parseNotOk(str, extra) |
michael@0 | 343 | { |
michael@0 | 344 | var result = parseOk(str, extra); |
michael@0 | 345 | result.times = [ [ 0, -100 ] ]; |
michael@0 | 346 | return result; |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | function createAnim(attr) |
michael@0 | 350 | { |
michael@0 | 351 | const svgns = "http://www.w3.org/2000/svg"; |
michael@0 | 352 | var anim = document.createElementNS(svgns, 'animate'); |
michael@0 | 353 | anim.setAttribute('attributeName','cx'); |
michael@0 | 354 | anim.setAttribute('dur','10s'); |
michael@0 | 355 | anim.setAttribute('begin','0s'); |
michael@0 | 356 | anim.setAttribute('fill','freeze'); |
michael@0 | 357 | for (name in attr) { |
michael@0 | 358 | anim.setAttribute(name, attr[name]); |
michael@0 | 359 | } |
michael@0 | 360 | return document.getElementById('circle').appendChild(anim); |
michael@0 | 361 | } |
michael@0 | 362 | |
michael@0 | 363 | function checkSample(anim, expectedValue, sampleTime, caseNum) |
michael@0 | 364 | { |
michael@0 | 365 | var msg = "Test case " + caseNum + |
michael@0 | 366 | " (keyTimes: '" + anim.getAttribute('keyTimes') + "'" + |
michael@0 | 367 | " calcMode: " + anim.getAttribute('calcMode') + "), " + |
michael@0 | 368 | "t=" + sampleTime + |
michael@0 | 369 | ": Unexpected sample value:"; |
michael@0 | 370 | is(anim.targetElement.cx.animVal.value, expectedValue, msg); |
michael@0 | 371 | } |
michael@0 | 372 | |
michael@0 | 373 | function checkLineCapSample(anim, expectedValue, sampleTime, caseDescr) |
michael@0 | 374 | { |
michael@0 | 375 | var msg = "Test case " + caseDescr + |
michael@0 | 376 | " (keyTimes: '" + anim.getAttribute('keyTimes') + "'" + |
michael@0 | 377 | " calcMode: " + anim.getAttribute('calcMode') + "), " + |
michael@0 | 378 | "t=" + sampleTime + |
michael@0 | 379 | ": Unexpected sample value:"; |
michael@0 | 380 | var actualValue = |
michael@0 | 381 | window.getComputedStyle(anim.targetElement, null). |
michael@0 | 382 | getPropertyValue('stroke-linecap'); |
michael@0 | 383 | is(actualValue, expectedValue, msg); |
michael@0 | 384 | } |
michael@0 | 385 | |
michael@0 | 386 | window.addEventListener("load", main, false); |
michael@0 | 387 | ]]> |
michael@0 | 388 | </script> |
michael@0 | 389 | </pre> |
michael@0 | 390 | </body> |
michael@0 | 391 | </html> |