From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../webkit/PerformanceTests/MotionMark/about.html | 52 + .../PerformanceTests/MotionMark/developer.html | 175 + .../webkit/PerformanceTests/MotionMark/index.html | 67 + .../resources/debug-runner/animometer.css | 774 ++ .../resources/debug-runner/animometer.js | 703 ++ .../MotionMark/resources/debug-runner/graph.js | 615 ++ .../MotionMark/resources/debug-runner/tests.js | 345 + .../MotionMark/resources/extensions.js | 670 ++ .../MotionMark/resources/runner/animometer.css | 520 ++ .../MotionMark/resources/runner/animometer.js | 626 ++ .../resources/runner/benchmark-runner.js | 179 + .../MotionMark/resources/runner/crystal.svg | 92 + .../MotionMark/resources/runner/lines.svg | 26 + .../MotionMark/resources/runner/logo.svg | 26 + .../MotionMark/resources/runner/tests.js | 81 + .../MotionMark/resources/statistics.js | 397 + .../MotionMark/resources/strings.js | 51 + .../MotionMark/tests/3d/resources/webgl.js | 184 + .../MotionMark/tests/3d/webgl.html | 64 + .../bouncing-particles/bouncing-canvas-images.html | 26 + .../bouncing-particles/bouncing-canvas-shapes.html | 18 + .../bouncing-particles/bouncing-css-images.html | 22 + .../bouncing-particles/bouncing-css-shapes.html | 33 + .../bouncing-particles/bouncing-svg-images.html | 18 + .../bouncing-particles/bouncing-svg-shapes.html | 18 + .../bouncing-particles/bouncing-tagged-images.html | 22 + .../resources/bouncing-canvas-images.js | 47 + .../resources/bouncing-canvas-particles.js | 88 + .../resources/bouncing-canvas-shapes.js | 87 + .../resources/bouncing-css-images.js | 61 + .../resources/bouncing-css-shapes.js | 86 + .../resources/bouncing-particles.js | 123 + .../resources/bouncing-svg-images.js | 43 + .../resources/bouncing-svg-particles.js | 67 + .../resources/bouncing-svg-shapes.js | 101 + .../resources/bouncing-tagged-images.js | 106 + .../tests/bouncing-particles/resources/image1.jpg | Bin 0 -> 64004 bytes .../tests/bouncing-particles/resources/image2.jpg | Bin 0 -> 71981 bytes .../tests/bouncing-particles/resources/image3.jpg | Bin 0 -> 71319 bytes .../tests/bouncing-particles/resources/image4.jpg | Bin 0 -> 96373 bytes .../tests/bouncing-particles/resources/image5.jpg | Bin 0 -> 135674 bytes .../tests/dom/compositing-transforms.html | 24 + .../MotionMark/tests/dom/focus.html | 51 + .../MotionMark/tests/dom/leaves.html | 26 + .../MotionMark/tests/dom/particles.html | 24 + .../tests/dom/resources/compositing-transforms.js | 66 + .../tests/dom/resources/dom-particles.js | 73 + .../MotionMark/tests/dom/resources/focus.js | 166 + .../MotionMark/tests/dom/resources/leaves.js | 48 + .../MotionMark/tests/master/canvas-stage.html | 17 + .../MotionMark/tests/master/focus.html | 29 + .../MotionMark/tests/master/image-data.html | 28 + .../MotionMark/tests/master/leaves.html | 25 + .../MotionMark/tests/master/multiply.html | 53 + .../tests/master/resources/canvas-stage.js | 52 + .../tests/master/resources/canvas-tests.js | 311 + .../MotionMark/tests/master/resources/compass.svg | 7 + .../tests/master/resources/compass100.png | Bin 0 -> 3048 bytes .../MotionMark/tests/master/resources/console.svg | 6 + .../tests/master/resources/console100.png | Bin 0 -> 944 bytes .../tests/master/resources/contribute.svg | 6 + .../tests/master/resources/contribute100.png | Bin 0 -> 3599 bytes .../MotionMark/tests/master/resources/debugger.svg | 5 + .../tests/master/resources/debugger100.png | Bin 0 -> 2473 bytes .../MotionMark/tests/master/resources/focus.js | 129 + .../tests/master/resources/image-data.js | 181 + .../tests/master/resources/inspector.svg | 6 + .../tests/master/resources/inspector100.png | Bin 0 -> 1477 bytes .../MotionMark/tests/master/resources/layout.svg | 6 + .../tests/master/resources/layout100.png | Bin 0 -> 423 bytes .../MotionMark/tests/master/resources/leaves.js | 135 + .../MotionMark/tests/master/resources/multiply.js | 119 + .../MotionMark/tests/master/resources/particles.js | 112 + .../tests/master/resources/performance.svg | 6 + .../tests/master/resources/performance100.png | Bin 0 -> 2546 bytes .../MotionMark/tests/master/resources/script.svg | 5 + .../tests/master/resources/script100.png | Bin 0 -> 3192 bytes .../tests/master/resources/shortcuts.svg | 5 + .../tests/master/resources/shortcuts100.png | Bin 0 -> 2763 bytes .../tests/master/resources/standards.svg | 6 + .../tests/master/resources/standards100.png | Bin 0 -> 4363 bytes .../MotionMark/tests/master/resources/storage.svg | 5 + .../tests/master/resources/storage100.png | Bin 0 -> 3167 bytes .../MotionMark/tests/master/resources/styles.svg | 5 + .../tests/master/resources/styles100.png | Bin 0 -> 3875 bytes .../tests/master/resources/svg-particles.js | 111 + .../MotionMark/tests/master/resources/text.js | 116 + .../MotionMark/tests/master/resources/timeline.svg | 6 + .../tests/master/resources/timeline100.png | Bin 0 -> 2039 bytes .../MotionMark/tests/master/svg-particles.html | 38 + .../MotionMark/tests/master/text.html | 82 + .../MotionMark/tests/resources/main.js | 934 ++ .../MotionMark/tests/resources/math.js | 268 + .../MotionMark/tests/resources/stage.css | 27 + .../MotionMark/tests/resources/star.svg | 8 + .../MotionMark/tests/resources/yin-yang.png | Bin 0 -> 4082 bytes .../MotionMark/tests/resources/yin-yang.svg | 17 + .../tests/simple/resources/simple-canvas-paths.js | 453 + .../tests/simple/resources/simple-canvas.js | 35 + .../tests/simple/resources/tiled-canvas-image.js | 119 + .../tests/simple/simple-canvas-paths.html | 18 + .../tests/simple/tiled-canvas-image.html | 16 + .../tests/template/resources/template-canvas.js | 89 + .../tests/template/resources/template-css.js | 46 + .../tests/template/resources/template-svg.js | 46 + .../MotionMark/tests/template/template-canvas.html | 16 + .../MotionMark/tests/template/template-css.html | 16 + .../MotionMark/tests/template/template-svg.html | 16 + .../webkit/PerformanceTests/MotionMark/version | 2 + .../Speedometer/InteractiveRunner.html | 173 + .../PerformanceTests/Speedometer/README_MOZILLA | 13 + .../webkit/PerformanceTests/Speedometer/index.html | 107 + .../Speedometer/resources/benchmark-report.js | 105 + .../Speedometer/resources/benchmark-runner.js | 305 + .../resources/flightjs-example-app/LICENSE.md | 19 + .../resources/flightjs-example-app/README.md | 5 + .../flightjs-example-app/app/boot/page.js | 47 + .../app/component_data/compose_box.js | 93 + .../app/component_data/mail_items.js | 68 + .../app/component_data/move_to.js | 52 + .../app/component_ui/compose_box.js | 113 + .../app/component_ui/folders.js | 34 + .../app/component_ui/mail_controls.js | 67 + .../app/component_ui/mail_items.js | 61 + .../app/component_ui/move_to_selector.js | 79 + .../app/component_ui/with_select.js | 64 + .../flightjs-example-app/app/css/custom.css | 102 + .../resources/flightjs-example-app/app/data.js | 110 + .../flightjs-example-app/app/templates.js | 62 + .../bootstrap/css/bootstrap-responsive.css | 1092 +++ .../bootstrap/css/bootstrap-responsive.min.css | 9 + .../components/bootstrap/css/bootstrap.css | 2470 +++++ .../components/bootstrap/css/bootstrap.min.css | 9 + .../bootstrap/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../bootstrap/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../components/bootstrap/js/bootstrap.js | 2159 +++++ .../components/bootstrap/js/bootstrap.min.js | 6 + .../components/es5-shim/.gitignore | 2 + .../components/es5-shim/CHANGES | 93 + .../components/es5-shim/CONTRIBUTORS.md | 25 + .../components/es5-shim/LICENSE | 19 + .../components/es5-shim/README.md | 161 + .../components/es5-shim/component.json | 54 + .../components/es5-shim/es5-sham.js | 326 + .../components/es5-shim/es5-sham.min.js | 6 + .../components/es5-shim/es5-shim.js | 778 ++ .../components/es5-shim/es5-shim.min.js | 13 + .../components/es5-shim/package.json | 31 + .../components/es5-shim/tests/helpers/h-kill.js | 59 + .../es5-shim/tests/helpers/h-matchers.js | 34 + .../components/es5-shim/tests/helpers/h.js | 3 + .../components/es5-shim/tests/index.html | 62 + .../components/es5-shim/tests/lib/jasmine-html.js | 190 + .../components/es5-shim/tests/lib/jasmine.css | 166 + .../components/es5-shim/tests/lib/jasmine.js | 2477 +++++ .../es5-shim/tests/lib/jasmine_favicon.png | Bin 0 -> 905 bytes .../components/es5-shim/tests/lib/json2.js | 478 + .../components/es5-shim/tests/spec/s-array.js | 1070 +++ .../components/es5-shim/tests/spec/s-date.js | 40 + .../components/es5-shim/tests/spec/s-function.js | 137 + .../components/es5-shim/tests/spec/s-object.js | 84 + .../components/es5-shim/tests/spec/s-string.js | 11 + .../components/flight/.travis.yml | 7 + .../components/flight/lib/advice.js | 69 + .../components/flight/lib/component.js | 308 + .../components/flight/lib/compose.js | 86 + .../components/flight/lib/index.js | 30 + .../components/flight/lib/logger.js | 93 + .../components/flight/lib/registry.js | 220 + .../components/flight/lib/utils.js | 236 + .../components/flight/tools/debug/debug.js | 157 + .../components/jasmine-flight/LICENSE.md | 19 + .../components/jasmine-flight/README.md | 145 + .../components/jasmine-flight/bower.json | 30 + .../jasmine-flight/lib/jasmine-flight.js | 444 + .../jasmine-jquery/lib/jasmine-jquery.js | 659 ++ .../components/jquery/component.json | 13 + .../components/jquery/composer.json | 23 + .../components/jquery/jquery.js | 9472 ++++++++++++++++++++ .../components/jquery/jquery.min.js | 2 + .../components/mustache/mustache.js | 635 ++ .../components/requirejs/require.js | 1993 ++++ .../resources/flightjs-example-app/index.html | 60 + .../resources/flightjs-example-app/karma.conf.js | 58 + .../resources/flightjs-example-app/package.json | 11 + .../resources/flightjs-example-app/requireMain.js | 24 + .../Speedometer/resources/gauge.png | Bin 0 -> 15101 bytes .../Speedometer/resources/gauge@2x.png | Bin 0 -> 33403 bytes .../Speedometer/resources/logo.png | Bin 0 -> 9037 bytes .../Speedometer/resources/logo@2x.png | Bin 0 -> 19309 bytes .../Speedometer/resources/main.css | 286 + .../PerformanceTests/Speedometer/resources/main.js | 246 + .../Speedometer/resources/tests.js | 580 ++ .../StyleBench/InteractiveRunner.html | 174 + .../PerformanceTests/StyleBench/README_MOZILLA | 13 + .../webkit/PerformanceTests/StyleBench/index.html | 79 + .../PerformanceTests/StyleBench/mozilla.patch | 86 + .../StyleBench/resources/benchmark-report.js | 103 + .../StyleBench/resources/benchmark-runner.js | 299 + .../StyleBench/resources/gauge.png | 0 .../StyleBench/resources/gauge@2x.png | 0 .../PerformanceTests/StyleBench/resources/main.css | 286 + .../PerformanceTests/StyleBench/resources/main.js | 246 + .../StyleBench/resources/style-bench.html | 32 + .../StyleBench/resources/style-bench.js | 511 ++ .../PerformanceTests/StyleBench/resources/tests.js | 40 + .../SunSpider/sunspider-0.9.1/3d-cube.js | 337 + .../SunSpider/sunspider-0.9.1/3d-morph.js | 54 + .../SunSpider/sunspider-0.9.1/3d-raytrace.js | 441 + .../sunspider-0.9.1/access-binary-trees.js | 50 + .../SunSpider/sunspider-0.9.1/access-fannkuch.js | 66 + .../SunSpider/sunspider-0.9.1/access-nbody.js | 169 + .../SunSpider/sunspider-0.9.1/access-nsieve.js | 38 + .../sunspider-0.9.1/bitops-3bit-bits-in-byte.js | 32 + .../sunspider-0.9.1/bitops-bits-in-byte.js | 21 + .../sunspider-0.9.1/bitops-bitwise-and.js | 28 + .../sunspider-0.9.1/bitops-nsieve-bits.js | 32 + .../sunspider-0.9.1/controlflow-recursive.js | 25 + .../SunSpider/sunspider-0.9.1/crypto-aes.js | 422 + .../SunSpider/sunspider-0.9.1/crypto-md5.js | 286 + .../SunSpider/sunspider-0.9.1/crypto-sha1.js | 224 + .../SunSpider/sunspider-0.9.1/date-format-tofte.js | 299 + .../SunSpider/sunspider-0.9.1/date-format-xparb.js | 417 + .../SunSpider/sunspider-0.9.1/math-cordic.js | 95 + .../SunSpider/sunspider-0.9.1/math-partial-sums.js | 33 + .../sunspider-0.9.1/math-spectral-norm.js | 51 + .../SunSpider/sunspider-0.9.1/regexp-dna.js | 1712 ++++ .../SunSpider/sunspider-0.9.1/string-base64.js | 135 + .../SunSpider/sunspider-0.9.1/string-fasta.js | 85 + .../SunSpider/sunspider-0.9.1/string-tagcloud.js | 265 + .../sunspider-0.9.1/string-unpack-code.js | 68 + .../sunspider-0.9.1/string-validate-input.js | 89 + .../sunspider-0.9.1/sunspider-standalone-driver.js | 71 + .../SunSpider/sunspider-1.0.1/json2.js | 481 + .../sunspider-1.0.1/sunspider-1.0.1/driver.html | 132 + .../sunspider-1.0.1/sunspider-1.0.1/results.html | 108 + .../sunspider-1.0.1/sunspider-test-contents.js | 7295 +++++++++++++++ .../sunspider-1.0.1/sunspider-test-prefix.js | 2 + .../sunspider-1.0.1/sunspider-analyze-results.js | 280 + .../sunspider-1.0.1/sunspider-compare-results.js | 396 + .../SunSpider/sunspider-1.0.1/sunspider.css | 31 + .../PerformanceTests/resources/statistics.js | 145 + .../webkit/PerformanceTests/six-speed/VERSION | 1 + .../webkit/PerformanceTests/six-speed/test.js | 85 + .../six-speed/tests/arrow-args.es5 | 16 + .../six-speed/tests/arrow-args.es6 | 14 + .../six-speed/tests/arrow-declare.es5 | 14 + .../six-speed/tests/arrow-declare.es6 | 13 + .../PerformanceTests/six-speed/tests/arrow.es5 | 15 + .../PerformanceTests/six-speed/tests/arrow.es6 | 14 + .../six-speed/tests/bindings-compound.es5 | 11 + .../six-speed/tests/bindings-compound.es6 | 14 + .../PerformanceTests/six-speed/tests/bindings.es5 | 8 + .../PerformanceTests/six-speed/tests/bindings.es6 | 10 + .../PerformanceTests/six-speed/tests/classes.es5 | 11 + .../PerformanceTests/six-speed/tests/classes.es6 | 13 + .../PerformanceTests/six-speed/tests/defaults.es5 | 14 + .../PerformanceTests/six-speed/tests/defaults.es6 | 13 + .../six-speed/tests/destructuring-simple.es5 | 14 + .../six-speed/tests/destructuring-simple.es6 | 14 + .../six-speed/tests/destructuring.es5 | 15 + .../six-speed/tests/destructuring.es6 | 13 + .../six-speed/tests/for-of-array.es5 | 13 + .../six-speed/tests/for-of-array.es6 | 13 + .../six-speed/tests/for-of-object.es5 | 13 + .../six-speed/tests/for-of-object.es6 | 24 + .../PerformanceTests/six-speed/tests/generator.es5 | 26 + .../PerformanceTests/six-speed/tests/generator.es6 | 14 + .../six-speed/tests/map-set-lookup.es5 | 21 + .../six-speed/tests/map-set-lookup.es6 | 18 + .../six-speed/tests/map-set-object.es5 | 21 + .../six-speed/tests/map-set-object.es6 | 18 + .../PerformanceTests/six-speed/tests/map-set.es5 | 16 + .../PerformanceTests/six-speed/tests/map-set.es6 | 17 + .../six-speed/tests/map-string.es5 | 12 + .../six-speed/tests/map-string.es6 | 12 + .../six-speed/tests/object-assign.es5 | 28 + .../six-speed/tests/object-assign.es6 | 22 + .../six-speed/tests/object-literal-ext.es5 | 15 + .../six-speed/tests/object-literal-ext.es6 | 14 + .../PerformanceTests/six-speed/tests/regex-u.es5 | 6 + .../PerformanceTests/six-speed/tests/regex-u.es6 | 6 + .../PerformanceTests/six-speed/tests/rest.es5 | 13 + .../PerformanceTests/six-speed/tests/rest.es6 | 13 + .../six-speed/tests/spread-generator.es5 | 27 + .../six-speed/tests/spread-generator.es6 | 11 + .../six-speed/tests/spread-literal.es5 | 8 + .../six-speed/tests/spread-literal.es6 | 5 + .../PerformanceTests/six-speed/tests/spread.es5 | 6 + .../PerformanceTests/six-speed/tests/spread.es6 | 6 + .../PerformanceTests/six-speed/tests/super.es5 | 23 + .../PerformanceTests/six-speed/tests/super.es6 | 25 + .../six-speed/tests/template_string.es5 | 7 + .../six-speed/tests/template_string.es6 | 7 + .../six-speed/tests/template_string_tag.es5 | 11 + .../six-speed/tests/template_string_tag.es6 | 11 + .../webkit/PerformanceTests/wasm-godot/godot.js | 4 + .../webkit/PerformanceTests/wasm-godot/godot.pck | Bin 0 -> 188116 bytes .../webkit/PerformanceTests/wasm-godot/index.html | 397 + .../webkit/PerformanceTests/webaudio/README.md | 13 + .../webkit/PerformanceTests/webaudio/benchmarks.js | 377 + .../webkit/PerformanceTests/webaudio/index.html | 47 + .../PerformanceTests/webaudio/think-mono-38000.wav | Bin 0 -> 160164 bytes .../PerformanceTests/webaudio/think-mono-44100.wav | Bin 0 -> 185868 bytes .../PerformanceTests/webaudio/think-mono-48000.wav | Bin 0 -> 202302 bytes .../PerformanceTests/webaudio/think-mono.wav | Bin 0 -> 185868 bytes .../webaudio/think-stereo-38000.wav | Bin 0 -> 320284 bytes .../webaudio/think-stereo-44100.wav | Bin 0 -> 371692 bytes .../webaudio/think-stereo-48000.wav | Bin 0 -> 404560 bytes .../webkit/PerformanceTests/webaudio/update.sh | 14 + .../PerformanceTests/webaudio/webaudio-bench.js | 240 + 311 files changed, 58678 insertions(+) create mode 100644 third_party/webkit/PerformanceTests/MotionMark/about.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/developer.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/index.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.css create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/graph.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/tests.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/extensions.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/statistics.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/strings.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/version create mode 100644 third_party/webkit/PerformanceTests/Speedometer/InteractiveRunner.html create mode 100644 third_party/webkit/PerformanceTests/Speedometer/README_MOZILLA create mode 100644 third_party/webkit/PerformanceTests/Speedometer/index.html create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-report.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-runner.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/LICENSE.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/README.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/boot/page.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/compose_box.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/mail_items.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/move_to.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/compose_box.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/folders.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_controls.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_items.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/move_to_selector.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/with_select.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/css/custom.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/data.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/templates.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.min.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.min.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings-white.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/js/bootstrap.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/js/bootstrap.min.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/.gitignore create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/CHANGES create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/CONTRIBUTORS.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/LICENSE create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/README.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/component.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/es5-sham.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/es5-sham.min.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/es5-shim.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/es5-shim.min.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/package.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/helpers/h-kill.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/helpers/h-matchers.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/helpers/h.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/index.html create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/lib/jasmine-html.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/lib/jasmine.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/lib/jasmine.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/lib/jasmine_favicon.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/lib/json2.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/spec/s-array.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/spec/s-date.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/spec/s-function.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/spec/s-object.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/es5-shim/tests/spec/s-string.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/.travis.yml create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/advice.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/component.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/compose.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/index.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/logger.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/registry.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/lib/utils.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/flight/tools/debug/debug.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jasmine-flight/LICENSE.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jasmine-flight/README.md create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jasmine-flight/bower.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jasmine-flight/lib/jasmine-flight.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jasmine-jquery/lib/jasmine-jquery.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jquery/component.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jquery/composer.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jquery/jquery.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/jquery/jquery.min.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/mustache/mustache.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/requirejs/require.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/index.html create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/karma.conf.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/package.json create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/requireMain.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/gauge.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/gauge@2x.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/logo.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/logo@2x.png create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/main.css create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/main.js create mode 100644 third_party/webkit/PerformanceTests/Speedometer/resources/tests.js create mode 100644 third_party/webkit/PerformanceTests/StyleBench/InteractiveRunner.html create mode 100644 third_party/webkit/PerformanceTests/StyleBench/README_MOZILLA create mode 100644 third_party/webkit/PerformanceTests/StyleBench/index.html create mode 100644 third_party/webkit/PerformanceTests/StyleBench/mozilla.patch create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-runner.js create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/gauge.png create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/gauge@2x.png create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/main.css create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/main.js create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/style-bench.html create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/style-bench.js create mode 100644 third_party/webkit/PerformanceTests/StyleBench/resources/tests.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-cube.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-morph.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-raytrace.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-binary-trees.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-fannkuch.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nbody.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nsieve.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-3bit-bits-in-byte.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bits-in-byte.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bitwise-and.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-nsieve-bits.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/controlflow-recursive.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-aes.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-md5.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-sha1.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-tofte.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-xparb.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-cordic.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-partial-sums.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-spectral-norm.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/regexp-dna.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-base64.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-fasta.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-tagcloud.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-unpack-code.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-validate-input.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/sunspider-standalone-driver.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/json2.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-1.0.1/driver.html create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-1.0.1/results.html create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-1.0.1/sunspider-test-contents.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-1.0.1/sunspider-test-prefix.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-analyze-results.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider-compare-results.js create mode 100644 third_party/webkit/PerformanceTests/SunSpider/sunspider-1.0.1/sunspider.css create mode 100644 third_party/webkit/PerformanceTests/resources/statistics.js create mode 100644 third_party/webkit/PerformanceTests/six-speed/VERSION create mode 100644 third_party/webkit/PerformanceTests/six-speed/test.js create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow-args.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow-args.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow-declare.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow-declare.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/arrow.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/bindings-compound.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/bindings-compound.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/bindings.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/bindings.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/classes.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/classes.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/defaults.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/defaults.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/destructuring-simple.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/destructuring-simple.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/destructuring.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/destructuring.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/for-of-array.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/for-of-array.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/for-of-object.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/for-of-object.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/generator.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/generator.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set-lookup.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set-lookup.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set-object.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set-object.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-set.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-string.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/map-string.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/object-assign.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/object-assign.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/object-literal-ext.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/object-literal-ext.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/regex-u.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/regex-u.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/rest.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/rest.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread-generator.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread-generator.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread-literal.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread-literal.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/spread.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/super.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/super.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/template_string.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/template_string.es6 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/template_string_tag.es5 create mode 100644 third_party/webkit/PerformanceTests/six-speed/tests/template_string_tag.es6 create mode 100644 third_party/webkit/PerformanceTests/wasm-godot/godot.js create mode 100644 third_party/webkit/PerformanceTests/wasm-godot/godot.pck create mode 100644 third_party/webkit/PerformanceTests/wasm-godot/index.html create mode 100644 third_party/webkit/PerformanceTests/webaudio/README.md create mode 100644 third_party/webkit/PerformanceTests/webaudio/benchmarks.js create mode 100644 third_party/webkit/PerformanceTests/webaudio/index.html create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-mono-38000.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-mono-44100.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-mono-48000.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-mono.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-stereo-38000.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-stereo-44100.wav create mode 100644 third_party/webkit/PerformanceTests/webaudio/think-stereo-48000.wav create mode 100755 third_party/webkit/PerformanceTests/webaudio/update.sh create mode 100644 third_party/webkit/PerformanceTests/webaudio/webaudio-bench.js (limited to 'third_party/webkit') diff --git a/third_party/webkit/PerformanceTests/MotionMark/about.html b/third_party/webkit/PerformanceTests/MotionMark/about.html new file mode 100644 index 0000000000..f14638a96b --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/about.html @@ -0,0 +1,52 @@ + + + + + + + About MotionMark + + + + +
+
+ + +
+

About MotionMark

+ +

MotionMark is a web benchmark that focuses on graphics performance. It draws multiple rendering elements, each of which uses the same set of graphics primitives. An element could be an SVG node, an HTML element with CSS style, or a series of canvas operations. Slight variations among the elements avoid trivial caching optimizations by the browser. Although fairly simple, the effects were chosen to reflect techniques commonly used on the web. Tests are visually rich, being designed to stress the graphics system rather than JavaScript.

+ +

After an initial warm-up, each test runs for a fixed period of time. Based on measurements of the browser’s frame rate, MotionMark adjusts the number of elements to draw, and concentrates around a narrow range where the browser starts to fail animating at 60 frames per second (fps). A piecewise linear regression is applied to the data, and the change point is reported as the test's score. The confidence interval is calculated through bootstrapping. MotionMark calculates the geometric mean of all of the tests’ scores to report the single score for the run.

+ +

MotionMark can be run on a wide variety of devices. Using the device’s screen dimensions it adjusts the drawing area into one of three sizes:

+ +
    +
  1. Small (568 x 320), targeted at mobile phones
  2. +
  3. Medium (900 x 600), targeted at tablets and laptops
  4. +
  5. Large (1600 x 800), targeted at desktops
  6. +
+ +

The design of the benchmark is modular. This makes it easy to write new tests and use different controllers, which can assist a developer working on improving the performance of a web engine. For the purpose of a public benchmark, the MotionMark master suite tests a variety of drawing operations using techniques including CSS, SVG, and Canvas:

+ +
    +
  • Multiply: CSS border radius, transforms, opacity
  • +
  • Arcs and Fills: Canvas path fills and arcs
  • +
  • Leaves: CSS-transformed elements
  • +
  • Paths: Canvas line, quadratic, and Bezier paths
  • +
  • Lines: Canvas line segments
  • +
  • Focus: CSS blur filter, opacity
  • +
  • Images: Canvas getImageData() and putImageData()
  • +
  • Design: HTML text rendering
  • +
  • Suits: SVG clip paths, gradients and transforms
  • +
+ +

To achieve consistent results on mobile devices, put the device in landscape orientation. On laptops and desktops, use the default display resolution and make the browser window fullscreen. Make sure that screen automatic display sleep is turned off or set to longer than 8 minutes.

+ +
+
+
+
+ + \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/MotionMark/developer.html b/third_party/webkit/PerformanceTests/MotionMark/developer.html new file mode 100644 index 0000000000..d7387a0e48 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/developer.html @@ -0,0 +1,175 @@ + + + + + + + MotionMark 1.0 - developer + + + + + + + + + + + + + + + + + + +
+
+

MotionMark

+
+
+
+

Suites:

+
    +
    Drop results here
    +
    +
    +

    Options:

    +
    +
      +
    • + +
    • +
    • +

      Display:

      +
        +
      • +
      • +
      +
    • +
    • +

      Tiles:

      +
        +
      • +
      • +
      +
    • +
    • +

      Adjusting the test complexity:

      +
        +
      • +
      • +
      • +
      • +
      • +
      +
    • +
    • + +
    • +
    • +

      Kalman filter estimated error:

      +
        +
      • +
      • +
      +
    • +
    • +

      Time measurement method:

      +
        +
      • +
      • +
      • +
      +
    • +
    +
    +
    +
    +

    For accurate results, please take the browser window full screen, or rotate the device to landscape orientation.

    +
    + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +

    MotionMark score

    +
    + on a small screen (phone) + on a medium screen (laptop, tablet) + on a large screen (desktop) +
    +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    + 'j': Show JSON results
    + 's': Select various results for copy/paste (use repeatedly to cycle) +

    +
    +
    +
    +
    +
    + +

    Graph:

    +

    +

    +
    + +
    +
    +
    +
    + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/index.html b/third_party/webkit/PerformanceTests/MotionMark/index.html new file mode 100644 index 0000000000..c1b1e2e58f --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/index.html @@ -0,0 +1,67 @@ + + + + + + + MotionMark 1.0 + + + + + + + + + + + + + + + +
    +
    + +
    +

    MotionMark is a graphics benchmark that measures a browser’s capability to animate complex scenes at a target frame rate.

    + +

    More details about the benchmark are available. Bigger scores are better.

    +

    For accurate results, please take your browser window full screen, or rotate your device to landscape orientation.

    +

    Please rotate your device.

    + +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    + on a small screen (phone) + on a medium screen (laptop, tablet) + on a large screen (desktop) +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.css b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.css new file mode 100644 index 0000000000..7fbf31ee7d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.css @@ -0,0 +1,774 @@ +body { + font-size: initial; +} + +body.showing-intro, +body.showing-results, +body.showing-test-graph { + background-color: rgb(96, 96, 96); + background-image: initial; + background-repeat: initial; + background-size: initial; + animation: initial; + will-change: initial; + + color: rgb(235, 235, 235); +} + +section .body { + margin-left: 0; + max-width: initial; + transform: none; +} + +h1 { + font-size: 3em; + margin: 1.5em 0 .5em; + text-align: center; +} + +button { + transform: none !important; + min-width: initial; + transition: none; + animation: none; + will-change: initial; + + display: block; + font-size: 1.5em; + border: 2px solid rgb(235, 235, 235); + color: rgb(235, 235, 235); + background: transparent; + border-radius: 10px; + padding: .5em 2em; +} + +button:hover { + background-color: rgba(255, 255, 255, .1); + cursor: pointer; +} + +button:active { + color: inherit; + background-color: rgba(255, 255, 255, .2); +} + +button:disabled { + border-color: rgba(235, 235, 235, .5); + color: rgba(235, 235, 235, .5); +} + +@media screen and (max-device-width: 414px), + screen and (max-device-height: 414px) and (orientation: landscape) { + h1 { + font-size: 2.5em; + } + + section { + box-sizing: border-box; + width: 100%; + height: 100%; + padding: 0 5px; + } +} + +/* -------------------------------------------------------------------------- */ +/* Tree */ +/* -------------------------------------------------------------------------- */ + +.tree { + padding: 0; + list-style-type: none; +} + +.tree .expand-button { + position: absolute; + clip: rect(0, 0, 0, 0); +} + +.tree .expand-button ~ ul { + display: none; +} + +.tree .expand-button:checked ~ ul { + display: block; +} + +.tree ul { + list-style-type:none; +} + +.tree li { + position: relative; + padding: 0 0 1em 1em; +} + +.tree ul li { + list-style:none; + padding: 1em 0 0 0em; +} + +.tree > li:last-child { + padding-bottom: 0; +} + +.tree-label { + position: relative; + display: inline-block; +} + +label.tree-label { + cursor: pointer; +} + +.tree > li > label.tree-label:before { + position: relative; + z-index: 1; + float: left; + margin: 0 0 0 -2em; + width: 1em; + height: 1em; + content: '\25BA'; + text-align: center; + line-height: 2.5em; + font-size: .5em; +} + +.tree > li > :checked ~ label.tree-label:before { + content: '\25BC'; +} + +.tree .link { + cursor: pointer; + color: #999; + font-style: italic; + margin-left: 2em; +} + +@media screen and (max-device-width: 414px), + screen and (max-device-height: 414px) and (orientation: landscape) { + .tree { + padding-left: 1em; + } + .tree > li > label.tree-label:before { + font-size: 1em; + margin-left: -1.75em; + line-height: 1em; + } +} + +/* -------------------------------------------------------------------------- */ +/* Intro Section */ +/* -------------------------------------------------------------------------- */ + +#intro { + padding: 0; + opacity: initial; + transition: none; +} + +#intro .body > p { + padding: 1em 0; + margin: 0 auto; + text-align: center; +} + +#intro .start-benchmark { + padding: 10vh 0; + text-align: center; +} + +#intro .start-benchmark p { + color: hsl(11, 72%, 50%); + margin-bottom: 1em; + -apple-trailing-word: -apple-partially-balanced; +} + +#intro .start-benchmark button { + margin: 0 auto; +} + + +@media screen and (max-device-width: 414px), + screen and (max-device-height: 414px) and (orientation: landscape) { + #intro.selected { + display: flex; + align-items: center; + justify-content: flex-start; + flex-flow: column; + } + + #intro p { + padding-left: 20px; + padding-right: 20px; + font-size: 1.5em; + } +} + +#intro h2 { + font-size: 1.2em; +} + +#intro .body > div:first-of-type { + width: 100%; + margin: 2em 0 0; + flex-direction: row; + display: flex; + align-content: flex-start; +} + +#suites { + padding-left: 15vw; + padding-right: 3em; + flex: 1 1 30%; +} + +#options { + flex: 10 1 auto; +} + +#intro input[type="number"] { + width: 50px; +} + +#suites input[type="number"] { + display: none; + float: right; +} + +#suites input[type="number"].selected { + display: inline; + margin: 0; +} + +#suites ul ul { + font-size: .8em; + margin: 0; + padding: 0 0 0 1em; +} + +#suites > div { + margin: 3em 0; +} + +#drop-target { + font-size: 1em; + border-radius: 10px; + padding: .5em 2em; + border: 2px solid rgb(235, 235, 235); + color: rgb(235, 235, 235); +} + +#drop-target:hover { + background-color: rgba(255, 255, 255, .1); + cursor: pointer; +} + +#options ul { + margin: 0; + padding: 0; + list-style: none; +} + +#options h3 { + font-size: 1em; + font-weight: inherit; + margin: 0 0 .3em 0; + padding: 0; +} + +#options > form > ul > li { + padding: 0 0 1em 0; +} + +#options ul ul { + padding: 0; +} + +#options li { + padding: .1em 0; +} + +#intro > p { + padding: 0 5px 1em; + font-size: 1em; +} + +#intro .start-benchmark { + padding: 0 0 10vh; + margin-top: 0; +} + +#intro .start-benchmark p { + color: hsl(11, 100%, 66%); +} + +@media screen and (max-device-width: 414px), + screen and (max-device-height: 414px) and (orientation: landscape) { + #intro .body > div:first-of-type { + flex-direction: column; + } + + #suites, + #options { + padding: 0 5px; + margin: 0; + flex: 0 0 auto; + } +} + +/* -------------------------------------------------------------------------- */ +/* Running Section */ +/* -------------------------------------------------------------------------- */ + +#running-test { + display: flex; + align-items: center; + justify-content: center; +} + +#progress { + display: none; +} + +.display-progress-bar #progress { + display: block; + position: fixed; + top: 0; + left: 0; + height: 6px; + width: 100%; + background-color: rgb(128, 128, 128); +} + +.display-progress-bar #progress-completed { + position: absolute; + top: 0; + left: 0; + height: 6px; + width: 0; + background-color: rgb(235, 96, 32); +} + +body.showing-test-container.tiles-big { + overflow: hidden; +} + +body.showing-test-container.tiles-classic { + width: 3000px; + height: 3000px; + overflow: scroll; +} + +/* -------------------------------------------------------------------------- */ +/* Results Section */ +/* -------------------------------------------------------------------------- */ + +#results { + text-align: center; +} + +#results h1, #test-graph h1 { + font-size: 2em; +} + +#results button.small-button { + border: 1px solid rgba(235, 235, 235, .9); + color: rgba(235, 235, 235, .9); + border-radius: 2px; + padding: 1px 4px; + margin: 0 0 0 1em; + font-size: 9px; +} + +#results button.small-button:active { + background-color: rgba(235, 235, 235, .2); + color: inherit; +} + +#results .score, +#test-graph .score { + font-size: 3em; + font-weight: bold; + margin: 0; +} + +#results .confidence, +#test-graph .confidence { + margin-top: 0; + margin-bottom: 1em; + font-size: 1.5em; + font-weight: 400; + text-indent: inherit; + color: inherit; +} + +#results-tables { + direction: rtl; + + display: flex; + + align-items: center; + justify-content: center; + + margin: 3em 0; +} + +#results .table-container > div { + margin-left: 0; +} + +#results #results-score { + float: initial; +} + +#results #results-header { + width: initial; + position: initial; +} + +#results table { + direction: ltr; + min-width: initial; +} + +#results table td.suites-separator { + padding: .5em 0; +} + +#results table tr:nth-child(even) { + background-color: transparent; +} + +#results th { + padding: .5em 0; +} + +#results tr td { + padding: .25em 0; +} + +#results-header td, #results-header th { + text-align: left; +} +#results-header tr td { + padding-right: 1em; +} +#results-score td, #results-score th { + text-align: right; +} +#results .body > button { + margin: 1.5em auto .5em; +} +#results footer { + padding-bottom: 10vh; +} + +@media screen and (max-device-width: 414px), + screen and (max-device-height: 414px) and (orientation: landscape) { + #results.selected { + padding: 0 20px; + } +} + +#overlay { + background: rgba(0, 0, 10, .8); +} + +@supports (-webkit-backdrop-filter: blur(10px)) { + #overlay { + background: rgba(0, 0, 10, .4); + } +} + +#overlay > div div { + border: 1px solid rgb(241, 241, 241); +} + +#overlay button { + margin: 2em auto; + border-color: rgb(241, 241, 241); + color: rgb(241, 241, 241); +} + +#overlay button:hover { + background-color: rgba(255, 255, 255, .1); +} + +#overlay button:active { + background-color: rgba(255, 255, 255, .2); +} + +#results-data .average { + padding-left: 1em; + text-align: right; +} + +#results-data .stdev { + text-align: left; + padding-left: .25em; +} + +#results-data .left { + text-align: left; +} + +#results-data .right { + text-align: right; +} + +#results-data .pad-left { + padding-left: 1em; +} + +#results-data .pad-right { + padding-right: .25em; +} + +#results-data .small { + font-size: .8em; +} + +#results-tables td.noisy-results { + color: rgb(255, 104, 104); +} + +#results-tables div { + direction: ltr; + display: flex; + flex-direction: row; +} + +#test-graph { + flex: 1 0 calc(100% - 40px); +} + +#test-graph h1 { + margin-bottom: 0; +} + +#test-graph header { + position: relative; + text-align:center; +} + +#test-graph header button { + position: absolute; + top: 0; + left: 0; + border-width: 1px; + font-size: 1em; + padding: .5em 1em; +} + +#test-graph .score, #test-graph .confidence { + margin: 0; +} + +#test-graph nav { + position: absolute; + top: 1.5em; + right: 0; + font-size: .7em; + width: 28em; +} + +#test-graph nav ul { + margin: 0 30px 1em 0; + padding: 0; + list-style: none; +} + +#test-graph nav li { + padding: .1em 0; +} + +#test-graph nav li > span { + float: right; +} + +#test-graph nav.hide-data span { + display: none; +} + +/* -------------------------------------------------------------------------- */ +/* Graph Section */ +/* -------------------------------------------------------------------------- */ + +#test-graph-data { + z-index: 1; + font: 10px sans-serif; + color: rgb(235, 235, 235); +} + +#test-graph-data > svg { + fill: none; + overflow: visible; +} + +.axis path, +.axis line { + fill: none; + stroke: #999999; + shape-rendering: crispEdges; +} + +.axis text { + fill: #999; +} + +.yLeft.axis text { + fill: #7add49; +} +.yLeft.axis path, +.yLeft.axis line { + stroke: #7add49; +} +.yRight.axis text { + fill: #fa4925; +} +.yRight.axis path, +.yRight.axis line { + stroke: #fa4925; +} + +.axis.complexity .tick line { + stroke: rgba(200, 200, 200, .6); + stroke-width: 2px; +} + +.axis.complexity .domain, +.axis.complexity text { + stroke: transparent; + fill: transparent; +} + +.marker line { + stroke: #5493D6; +} + +.marker text { + fill: #999; +} + +.mean.complexity line { + stroke: hsla(100, 69%, 58%, .8); + stroke-width: 2px; +} + +.mean.complexity polygon { + fill: hsla(100, 69%, 58%, .05); +} + +.target-fps { + stroke: rgba(250, 73, 37, .4); + stroke-width: 1px; + stroke-dasharray: 10, 10; +} + +.mean.fps line { + stroke: hsla(10, 96%, 56%, .8); + stroke-width: 2px; +} + +.mean.fps polygon { + fill: hsla(10, 96%, 56%, .1); +} + +#regressions line { + stroke: rgba(200, 200, 200, .8); + stroke-width: 2px; +} + +#regressions circle { + fill: rgba(200, 200, 200, .8); +} + +.cursor line { + stroke: rgb(250, 250, 250); + stroke-width: 1px; +} + +.cursor circle, +.cursor text { + fill: rgb(250, 250, 250); +} + +#complexity path { + stroke: rgba(122, 221, 73, .7); + stroke-width: 2px; +} + +#complexity circle { + fill: rgb(122, 221, 73); +} + +#filteredFPS path { + stroke: hsla(30, 96%, 56%, .7); + stroke-width: 1px; +} + +#filteredFPS circle { + fill: hsl(30, 96%, 56%); +} + +#rawFPS path { + stroke: rgba(250, 73, 37, .7); + stroke-width: 1px; +} + +#rawFPS circle { + fill: rgb(250, 73, 37); +} + +#complexity-graph .regression line { + stroke: rgba(253, 253, 253, .8); + stroke-width: 2px; +} + +#complexity-graph .regression circle { + fill: rgba(253, 253, 253, .8); +} + +#complexity-graph .regression polygon { + fill: rgba(253, 253, 253, .05); +} + +#complexity-graph .raw.series line { + stroke: hsla(30, 96%, 56%, .3); + stroke-width: 1px; +} + +#complexity-graph .raw.regression line { + stroke: rgba(30, 96%, 86%, .6); +} + +#complexity-graph .raw.regression polygon { + stroke: rgba(30, 96%, 86%, .05); +} + +#complexity-graph .average.series circle { + fill: hsl(170, 96%, 56%); +} + +#complexity-graph .average.series line { + stroke: hsla(170, 96%, 56%, .2); + stroke-width: 2px; +} + +#complexity-graph .bootstrap .bar { + fill: hsla(260, 56%, 66%, .4); +} + +#complexity-graph .bootstrap .median line { + stroke: hsla(300, 56%, 66%, .8); + stroke-width: 2px; +} + +#complexity-graph .bootstrap .median circle { + fill: hsla(300, 56%, 66%, .8); +} + +#complexity-graph .bootstrap .median polygon { + fill: hsla(300, 56%, 66%, .05); +} diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.js b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.js new file mode 100644 index 0000000000..072cdcc762 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.js @@ -0,0 +1,703 @@ +ProgressBar = Utilities.createClass( + function(element, ranges) + { + this._element = element; + this._ranges = ranges; + this._currentRange = 0; + this._updateElement(); + }, { + + _updateElement: function() + { + this._element.style.width = (this._currentRange * (100 / this._ranges)) + "%"; + }, + + incrementRange: function() + { + ++this._currentRange; + this._updateElement(); + } +}); + +DeveloperResultsTable = Utilities.createSubclass(ResultsTable, + function(element, headers) + { + ResultsTable.call(this, element, headers); + }, { + + _addGraphButton: function(td, testName, testResult, testData) + { + var button = Utilities.createElement("button", { class: "small-button" }, td); + button.textContent = Strings.text.graph + "…"; + button.testName = testName; + button.testResult = testResult; + button.testData = testData; + + button.addEventListener("click", function(e) { + benchmarkController.showTestGraph(e.target.testName, e.target.testResult, e.target.testData); + }); + }, + + _isNoisyMeasurement: function(jsonExperiment, data, measurement, options) + { + const percentThreshold = 10; + const averageThreshold = 2; + + if (measurement == Strings.json.measurements.percent) + return data[Strings.json.measurements.percent] >= percentThreshold; + + if (jsonExperiment == Strings.json.frameLength && measurement == Strings.json.measurements.average) + return Math.abs(data[Strings.json.measurements.average] - options["frame-rate"]) >= averageThreshold; + + return false; + }, + + _addTest: function(testName, testResult, options, testData) + { + var row = Utilities.createElement("tr", {}, this.element); + + var isNoisy = false; + [Strings.json.complexity, Strings.json.frameLength].forEach(function (experiment) { + var data = testResult[experiment]; + for (var measurement in data) { + if (this._isNoisyMeasurement(experiment, data, measurement, options)) + isNoisy = true; + } + }, this); + + this._flattenedHeaders.forEach(function (header) { + var className = ""; + if (header.className) { + if (typeof header.className == "function") + className = header.className(testResult, options); + else + className = header.className; + } + + if (header.text == Strings.text.testName) { + if (isNoisy) + className += " noisy-results"; + var td = Utilities.createElement("td", { class: className }, row); + td.textContent = testName; + return; + } + + var td = Utilities.createElement("td", { class: className }, row); + if (header.title == Strings.text.graph) { + this._addGraphButton(td, testName, testResult, testData); + } else if (!("text" in header)) { + td.textContent = testResult[header.title]; + } else if (typeof header.text == "string") { + var data = testResult[header.text]; + if (typeof data == "number") + data = data.toFixed(2); + td.textContent = data; + } else + td.textContent = header.text(testResult); + }, this); + } +}); + +Utilities.extendObject(window.benchmarkRunnerClient, { + testsCount: null, + progressBar: null, + + initialize: function(suites, options) + { + this.testsCount = this.iterationCount * suites.reduce(function (count, suite) { return count + suite.tests.length; }, 0); + this.options = options; + }, + + willStartFirstIteration: function() + { + this.results = new ResultsDashboard(this.options); + this.progressBar = new ProgressBar(document.getElementById("progress-completed"), this.testsCount); + }, + + didRunTest: function(testData) + { + this.progressBar.incrementRange(); + this.results.calculateScore(testData); + } +}); + +Utilities.extendObject(window.sectionsManager, { + setSectionHeader: function(sectionIdentifier, title) + { + document.querySelector("#" + sectionIdentifier + " h1").textContent = title; + }, + + populateTable: function(tableIdentifier, headers, dashboard) + { + var table = new DeveloperResultsTable(document.getElementById(tableIdentifier), headers); + table.showIterations(dashboard); + } +}); + +window.optionsManager = +{ + valueForOption: function(name) + { + var formElement = document.forms["benchmark-options"].elements[name]; + if (formElement.type == "checkbox") + return formElement.checked; + else if (formElement.constructor === HTMLCollection) { + for (var i = 0; i < formElement.length; ++i) { + var radio = formElement[i]; + if (radio.checked) + return formElement.value; + } + return null; + } + return formElement.value; + }, + + updateUIFromLocalStorage: function() + { + var formElements = document.forms["benchmark-options"].elements; + + for (var i = 0; i < formElements.length; ++i) { + var formElement = formElements[i]; + var name = formElement.id || formElement.name; + var type = formElement.type; + + var value = localStorage.getItem(name); + if (value === null) + continue; + + if (type == "number") + formElements[name].value = +value; + else if (type == "checkbox") + formElements[name].checked = value == "true"; + else if (type == "radio") + formElements[name].value = value; + } + }, + + updateLocalStorageFromUI: function() + { + var formElements = document.forms["benchmark-options"].elements; + var options = {}; + + for (var i = 0; i < formElements.length; ++i) { + var formElement = formElements[i]; + var name = formElement.id || formElement.name; + var type = formElement.type; + + if (type == "number") + options[name] = +formElement.value; + else if (type == "checkbox") + options[name] = formElement.checked; + else if (type == "radio") { + var radios = formElements[name]; + if (radios.constructor === HTMLCollection) { + for (var j = 0; j < radios.length; ++j) { + var radio = radios[j]; + if (radio.checked) { + options[name] = radio.value; + break; + } + } + } else + options[name] = formElements[name].value; + } + + try { + localStorage.setItem(name, options[name]); + } catch (e) {} + } + + return options; + }, + + updateDisplay: function() + { + document.body.classList.remove("display-minimal"); + document.body.classList.remove("display-progress-bar"); + + document.body.classList.add("display-" + optionsManager.valueForOption("display")); + }, + + updateTiles: function() + { + document.body.classList.remove("tiles-big"); + document.body.classList.remove("tiles-classic"); + + document.body.classList.add("tiles-" + optionsManager.valueForOption("tiles")); + } +}; + +window.suitesManager = +{ + _treeElement: function() + { + return document.querySelector("#suites > .tree"); + }, + + _suitesElements: function() + { + return document.querySelectorAll("#suites > ul > li"); + }, + + _checkboxElement: function(element) + { + return element.querySelector("input[type='checkbox']:not(.expand-button)"); + }, + + _editElement: function(element) + { + return element.querySelector("input[type='number']"); + }, + + _editsElements: function() + { + return document.querySelectorAll("#suites input[type='number']"); + }, + + _localStorageNameForTest: function(suiteName, testName) + { + return suiteName + "/" + testName; + }, + + _updateSuiteCheckboxState: function(suiteCheckbox) + { + var numberEnabledTests = 0; + suiteCheckbox.testsElements.forEach(function(testElement) { + var testCheckbox = this._checkboxElement(testElement); + if (testCheckbox.checked) + ++numberEnabledTests; + }, this); + suiteCheckbox.checked = numberEnabledTests > 0; + suiteCheckbox.indeterminate = numberEnabledTests > 0 && numberEnabledTests < suiteCheckbox.testsElements.length; + }, + + isAtLeastOneTestSelected: function() + { + var suitesElements = this._suitesElements(); + + for (var i = 0; i < suitesElements.length; ++i) { + var suiteElement = suitesElements[i]; + var suiteCheckbox = this._checkboxElement(suiteElement); + + if (suiteCheckbox.checked) + return true; + } + + return false; + }, + + _onChangeSuiteCheckbox: function(event) + { + var selected = event.target.checked; + event.target.testsElements.forEach(function(testElement) { + var testCheckbox = this._checkboxElement(testElement); + testCheckbox.checked = selected; + }, this); + benchmarkController.updateStartButtonState(); + }, + + _onChangeTestCheckbox: function(suiteCheckbox) + { + this._updateSuiteCheckboxState(suiteCheckbox); + benchmarkController.updateStartButtonState(); + }, + + _createSuiteElement: function(treeElement, suite, id) + { + var suiteElement = Utilities.createElement("li", {}, treeElement); + var expand = Utilities.createElement("input", { type: "checkbox", class: "expand-button", id: id }, suiteElement); + var label = Utilities.createElement("label", { class: "tree-label", for: id }, suiteElement); + + var suiteCheckbox = Utilities.createElement("input", { type: "checkbox" }, label); + suiteCheckbox.suite = suite; + suiteCheckbox.onchange = this._onChangeSuiteCheckbox.bind(this); + suiteCheckbox.testsElements = []; + + label.appendChild(document.createTextNode(" " + suite.name)); + return suiteElement; + }, + + _createTestElement: function(listElement, test, suiteCheckbox) + { + var testElement = Utilities.createElement("li", {}, listElement); + var span = Utilities.createElement("label", { class: "tree-label" }, testElement); + + var testCheckbox = Utilities.createElement("input", { type: "checkbox" }, span); + testCheckbox.test = test; + testCheckbox.onchange = function(event) { + this._onChangeTestCheckbox(event.target.suiteCheckbox); + }.bind(this); + testCheckbox.suiteCheckbox = suiteCheckbox; + + suiteCheckbox.testsElements.push(testElement); + span.appendChild(document.createTextNode(" " + test.name + " ")); + + testElement.appendChild(document.createTextNode(" ")); + var link = Utilities.createElement("span", {}, testElement); + link.classList.add("link"); + link.textContent = "link"; + link.suiteName = Utilities.stripNonASCIICharacters(suiteCheckbox.suite.name); + link.testName = test.name; + link.onclick = function(event) { + var element = event.target; + var title = "Link to run “" + element.testName + "” with current options:"; + var url = location.href.split(/[?#]/)[0]; + var options = optionsManager.updateLocalStorageFromUI(); + Utilities.extendObject(options, { + "suite-name": element.suiteName, + "test-name": Utilities.stripNonASCIICharacters(element.testName) + }); + var complexity = suitesManager._editElement(element.parentNode).value; + if (complexity) + options.complexity = complexity; + prompt(title, url + Utilities.convertObjectToQueryString(options)); + }; + + var complexity = Utilities.createElement("input", { type: "number" }, testElement); + complexity.relatedCheckbox = testCheckbox; + complexity.oninput = function(event) { + var relatedCheckbox = event.target.relatedCheckbox; + relatedCheckbox.checked = true; + this._onChangeTestCheckbox(relatedCheckbox.suiteCheckbox); + }.bind(this); + return testElement; + }, + + createElements: function() + { + var treeElement = this._treeElement(); + + Suites.forEach(function(suite, index) { + var suiteElement = this._createSuiteElement(treeElement, suite, "suite-" + index); + var listElement = Utilities.createElement("ul", {}, suiteElement); + var suiteCheckbox = this._checkboxElement(suiteElement); + + suite.tests.forEach(function(test) { + this._createTestElement(listElement, test, suiteCheckbox); + }, this); + }, this); + }, + + updateEditsElementsState: function() + { + var editsElements = this._editsElements(); + var showComplexityInputs = ["fixed", "step"].indexOf(optionsManager.valueForOption("controller")) != -1; + + for (var i = 0; i < editsElements.length; ++i) { + var editElement = editsElements[i]; + if (showComplexityInputs) + editElement.classList.add("selected"); + else + editElement.classList.remove("selected"); + } + }, + + updateUIFromLocalStorage: function() + { + var suitesElements = this._suitesElements(); + + for (var i = 0; i < suitesElements.length; ++i) { + var suiteElement = suitesElements[i]; + var suiteCheckbox = this._checkboxElement(suiteElement); + var suite = suiteCheckbox.suite; + + suiteCheckbox.testsElements.forEach(function(testElement) { + var testCheckbox = this._checkboxElement(testElement); + var testEdit = this._editElement(testElement); + var test = testCheckbox.test; + + var str = localStorage.getItem(this._localStorageNameForTest(suite.name, test.name)); + if (str === null) + return; + + var value = JSON.parse(str); + testCheckbox.checked = value.checked; + testEdit.value = value.complexity; + }, this); + + this._updateSuiteCheckboxState(suiteCheckbox); + } + + benchmarkController.updateStartButtonState(); + }, + + updateLocalStorageFromUI: function() + { + var suitesElements = this._suitesElements(); + var suites = []; + + for (var i = 0; i < suitesElements.length; ++i) { + var suiteElement = suitesElements[i]; + var suiteCheckbox = this._checkboxElement(suiteElement); + var suite = suiteCheckbox.suite; + + var tests = []; + suiteCheckbox.testsElements.forEach(function(testElement) { + var testCheckbox = this._checkboxElement(testElement); + var testEdit = this._editElement(testElement); + var test = testCheckbox.test; + + if (testCheckbox.checked) { + test.complexity = testEdit.value; + tests.push(test); + } + + var value = { checked: testCheckbox.checked, complexity: testEdit.value }; + try { + localStorage.setItem(this._localStorageNameForTest(suite.name, test.name), JSON.stringify(value)); + } catch (e) {} + }, this); + + if (tests.length) + suites.push(new Suite(suiteCheckbox.suite.name, tests)); + } + + return suites; + }, + + suitesFromQueryString: function(suiteName, testName, oskey=null) + { + var suites = []; + var suiteRegExp = new RegExp(suiteName, "i"); + var testRegExp = new RegExp(testName, "i"); + + for (var i = 0; i < Suites.length; ++i) { + var suite = Suites[i]; + if (!Utilities.stripNonASCIICharacters(suite.name).match(suiteRegExp)) + continue; + + var test; + for (var j = 0; j < suite.tests.length; ++j) { + suiteTest = suite.tests[j]; + // MOZILLA: Run all the tests in a given suite + if (typeof(testName) === "undefined") { + let complexity = {"HTMLsuite": { + "CSSbouncingcircles": {"win": 322, "linux64": 322, "osx": 218}, + "CSSbouncingclippedrects": {"win": 520, "linux64": 520, "osx": 75}, + "CSSbouncinggradientcircles": {"win": 402, "linux64": 402, "osx": 97}, + "CSSbouncingblendcircles": {"win": 171, "linux64": 171, "osx": 254}, + "CSSbouncingfiltercircles": {"win": 189, "linux64": 189, "osx": 189}, + "CSSbouncingSVGimages": {"win": 329, "linux64": 329, "osx": 392}, + "CSSbouncingtaggedimages": {"win": 255, "linux64": 255, "osx": 351}, + "Leaves20": {"win": 262, "linux64": 262, "osx": 191}, + "Focus20": {"win": 15, "linux64": 15, "osx": 18}, + "DOMparticlesSVGmasks": {"win": 390, "linux64": 390, "osx": 54}, + "CompositedTransforms": {"win": 400, "linux64": 400, "osx": 75} + }, "Animometer": { + "Multiply": {"win": 391, "linux64": 391, "osx": 193}, + "CanvasArcs": {"win": 1287, "linux64": 1287, "osx": 575}, + "Leaves": {"win": 550, "linux64": 550, "osx": 271}, + "Paths": {"win": 4070, "linux64": 4070, "osx": 2024}, + "CanvasLines": {"win": 4692, "linux64": 4692, "osx": 10932}, + "Focus": {"win": 44, "linux64": 44, "osx": 32}, + "Images": {"win": 293, "linux64": 293, "osx": 188}, + "Design": {"win": 60, "linux64": 60, "osx": 17}, + "Suits": {"win": 210, "linux64": 210, "osx": 145} + } + }; + if (oskey == null) { + oskey = "linux64"; + } + suiteTest.complexity = complexity[suiteName][Utilities.stripNonASCIICharacters(suiteTest.name)][oskey]; + suites.push(new Suite(suiteName, [suiteTest])); + continue; + } + + if (Utilities.stripNonASCIICharacters(suiteTest.name).match(testRegExp)) { + test = suiteTest; + break; + } + } + + if (!test) + continue; + + suites.push(new Suite(suiteName, [test])); + }; + + return suites; + }, + + updateLocalStorageFromJSON: function(results) + { + for (var suiteName in results[Strings.json.results.tests]) { + var suiteResults = results[Strings.json.results.tests][suiteName]; + for (var testName in suiteResults) { + var testResults = suiteResults[testName]; + var data = testResults[Strings.json.controller]; + var complexity = Math.round(data[Strings.json.measurements.average]); + + var value = { checked: true, complexity: complexity }; + try { + localStorage.setItem(this._localStorageNameForTest(suiteName, testName), JSON.stringify(value)); + } catch (e) {} + } + } + } +} + +Utilities.extendObject(window.benchmarkController, { + initialize: function() + { + document.forms["benchmark-options"].addEventListener("change", benchmarkController.onBenchmarkOptionsChanged, true); + document.forms["graph-type"].addEventListener("change", benchmarkController.onGraphTypeChanged, true); + document.forms["time-graph-options"].addEventListener("change", benchmarkController.onTimeGraphOptionsChanged, true); + document.forms["complexity-graph-options"].addEventListener("change", benchmarkController.onComplexityGraphOptionsChanged, true); + optionsManager.updateUIFromLocalStorage(); + optionsManager.updateDisplay(); + optionsManager.updateTiles(); + + if (benchmarkController.startBenchmarkImmediatelyIfEncoded()) + return; + + benchmarkController.addOrientationListenerIfNecessary(); + suitesManager.createElements(); + suitesManager.updateUIFromLocalStorage(); + suitesManager.updateEditsElementsState(); + + var dropTarget = document.getElementById("drop-target"); + function stopEvent(e) { + e.stopPropagation(); + e.preventDefault(); + } + dropTarget.addEventListener("dragenter", stopEvent, false); + dropTarget.addEventListener("dragover", stopEvent, false); + dropTarget.addEventListener("dragleave", stopEvent, false); + dropTarget.addEventListener("drop", function (e) { + e.stopPropagation(); + e.preventDefault(); + + if (!e.dataTransfer.files.length) + return; + + var file = e.dataTransfer.files[0]; + + var reader = new FileReader(); + reader.filename = file.name; + reader.onload = function(e) { + var run = JSON.parse(e.target.result); + if (run.debugOutput instanceof Array) + run = run.debugOutput[0]; + benchmarkRunnerClient.results = new ResultsDashboard(run.options, run.data); + benchmarkController.showResults(); + }; + + reader.readAsText(file); + document.title = "File: " + reader.filename; + }, false); + }, + + updateStartButtonState: function() + { + var startButton = document.getElementById("run-benchmark"); + if ("isInLandscapeOrientation" in this && !this.isInLandscapeOrientation) { + startButton.disabled = true; + return; + } + startButton.disabled = !suitesManager.isAtLeastOneTestSelected(); + }, + + onBenchmarkOptionsChanged: function(event) + { + switch (event.target.name) { + case "controller": + suitesManager.updateEditsElementsState(); + break; + case "display": + optionsManager.updateDisplay(); + break; + case "tiles": + optionsManager.updateTiles(); + break; + } + }, + + startBenchmark: function() + { + benchmarkController.determineCanvasSize(); + benchmarkController.options = optionsManager.updateLocalStorageFromUI(); + benchmarkController.suites = suitesManager.updateLocalStorageFromUI(); + this._startBenchmark(benchmarkController.suites, benchmarkController.options, "running-test"); + }, + + startBenchmarkImmediatelyIfEncoded: function() + { + benchmarkController.options = Utilities.convertQueryStringToObject(location.search); + if (!benchmarkController.options) + return false; + + this.raptor = benchmarkController.options["raptor"]; + benchmarkController.suites = suitesManager.suitesFromQueryString(benchmarkController.options["suite-name"], + benchmarkController.options["test-name"], + benchmarkController.options["oskey"]); + if (!benchmarkController.suites.length) + return false; + + setTimeout(function() { + this._startBenchmark(benchmarkController.suites, benchmarkController.options, "running-test"); + }.bind(this), 0); + return true; + }, + + restartBenchmark: function() + { + this._startBenchmark(benchmarkController.suites, benchmarkController.options, "running-test"); + }, + + showResults: function() + { + if (!this.addedKeyEvent) { + document.addEventListener("keypress", this.handleKeyPress, false); + this.addedKeyEvent = true; + } + + var dashboard = benchmarkRunnerClient.results; + if (["ramp", "ramp30"].indexOf(dashboard.options["controller"]) != -1) + Headers.details[3].disabled = true; + else { + Headers.details[1].disabled = true; + Headers.details[4].disabled = true; + } + + if (dashboard.options[Strings.json.configuration]) { + document.body.classList.remove("small", "medium", "large"); + document.body.classList.add(dashboard.options[Strings.json.configuration]); + } + + var score = dashboard.score; + var item = dashboard._results['iterationsResults'][0]; + var fullNames = new Array; + var values = new Array; + for (var suite in item['testsResults']) { + for (var subtest in item['testsResults'][suite.toString()]) { + fullNames.push(suite.toString() + "-" + subtest.toString().replace(/ /g, '_')); + values.push(item['testsResults'][suite.toString()][subtest.toString()]['frameLength']['average']); + } + } + if (typeof tpRecordTime !== "undefined") { + tpRecordTime(values.join(','), 0, fullNames.join(',')); + } + if (this.raptor) { + _data = ['raptor-benchmark', 'motionmark', item['testsResults']]; + window.postMessage(_data, '*'); + window.sessionStorage.setItem('benchmark_results', JSON.stringify(_data)); + } + + var confidence = ((dashboard.scoreLowerBound / score - 1) * 100).toFixed(2) + + "% / +" + ((dashboard.scoreUpperBound / score - 1) * 100).toFixed(2) + "%"; + sectionsManager.setSectionScore("results", score.toFixed(2), confidence); + sectionsManager.populateTable("results-header", Headers.testName, dashboard); + sectionsManager.populateTable("results-score", Headers.score, dashboard); + sectionsManager.populateTable("results-data", Headers.details, dashboard); + sectionsManager.showSection("results", true); + + suitesManager.updateLocalStorageFromJSON(dashboard.results[0]); + }, + + showTestGraph: function(testName, testResult, testData) + { + sectionsManager.setSectionHeader("test-graph", testName); + sectionsManager.showSection("test-graph", true); + this.updateGraphData(testResult, testData, benchmarkRunnerClient.results.options); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/graph.js b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/graph.js new file mode 100644 index 0000000000..4803936219 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/graph.js @@ -0,0 +1,615 @@ +Utilities.extendObject(window.benchmarkController, { + updateGraphData: function(testResult, testData, options) + { + var element = document.getElementById("test-graph-data"); + element.innerHTML = ""; + element._testResult = testResult; + element._options = options; + + var margins = new Insets(30, 30, 30, 40); + var size = Point.elementClientSize(element); + size.y = window.innerHeight - element.offsetTop; + size = size.subtract(margins.size); + + // Convert from compact JSON output to propertied data + var samplesWithProperties = {}; + [Strings.json.controller, Strings.json.complexity, Strings.json.complexityAverage].forEach(function(seriesName) { + var series = testData[Strings.json.samples][seriesName]; + samplesWithProperties[seriesName] = series.toArray(); + }) + + this.createTimeGraph(testResult, samplesWithProperties[Strings.json.controller], testData[Strings.json.marks], testData[Strings.json.controller], options, margins, size); + this.onTimeGraphOptionsChanged(); + + this._showOrHideNodes(true, "form[name=graph-type]"); + document.forms["graph-type"].elements["type"] = "complexity"; + this.createComplexityGraph(testResult, testData[Strings.json.controller], samplesWithProperties, options, margins, size); + this.onComplexityGraphOptionsChanged(); + + this.onGraphTypeChanged(); + }, + + _addRegressionLine: function(parent, xScale, yScale, points, range, isAlongYAxis) + { + var polygon = []; + var line = [] + var xRange = isAlongYAxis ? range : 0; + var yRange = isAlongYAxis ? 0 : range; + for (var i = 0; i < points.length; ++i) { + var point = points[i]; + var x; + if (xRange instanceof Array) + x = xRange[0]; + else + x = point[0] + xRange; + polygon.push(xScale(x), yScale(point[1] + yRange)); + line.push(xScale(point[0]), yScale(point[1])); + } + for (var i = points.length - 1; i >= 0; --i) { + var point = points[i]; + var x; + if (xRange instanceof Array) + x = xRange[1]; + else + x = point[0] - xRange; + polygon.push(xScale(x), yScale(point[1] - yRange)); + } + parent.append("polygon") + .attr("points", polygon.join(",")); + parent.append("line") + .attr("x1", line[0]) + .attr("y1", line[1]) + .attr("x2", line[2]) + .attr("y2", line[3]); + }, + + _addRegression: function(data, svg, xScale, yScale) + { + svg.append("circle") + .attr("cx", xScale(data.segment1[1][0])) + .attr("cy", yScale(data.segment1[1][1])) + .attr("r", 5); + this._addRegressionLine(svg, xScale, yScale, data.segment1, data.stdev); + this._addRegressionLine(svg, xScale, yScale, data.segment2, data.stdev); + }, + + createComplexityGraph: function(result, timeRegressions, data, options, margins, size) + { + var svg = d3.select("#test-graph-data").append("svg") + .attr("id", "complexity-graph") + .attr("class", "hidden") + .attr("width", size.width + margins.left + margins.right) + .attr("height", size.height + margins.top + margins.bottom) + .append("g") + .attr("transform", "translate(" + margins.left + "," + margins.top + ")"); + + var timeSamples = data[Strings.json.controller]; + + var xMin = 100000, xMax = 0; + if (timeRegressions) { + timeRegressions.forEach(function(regression) { + for (var i = regression.startIndex; i <= regression.endIndex; ++i) { + xMin = Math.min(xMin, timeSamples[i].complexity); + xMax = Math.max(xMax, timeSamples[i].complexity); + } + }); + } else { + xMin = d3.min(timeSamples, function(s) { return s.complexity; }); + xMax = d3.max(timeSamples, function(s) { return s.complexity; }); + } + + var xScale = d3.scale.linear() + .range([0, size.width]) + .domain([xMin, xMax]); + var yScale = d3.scale.linear() + .range([size.height, 0]) + .domain([1000/20, 1000/60]); + + var xAxis = d3.svg.axis() + .scale(xScale) + .orient("bottom"); + var yAxis = d3.svg.axis() + .scale(yScale) + .tickValues([1000/20, 1000/25, 1000/30, 1000/35, 1000/40, 1000/45, 1000/50, 1000/55, 1000/60]) + .tickFormat(function(d) { return (1000 / d).toFixed(0); }) + .orient("left"); + + // x-axis + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + size.height + ")") + .call(xAxis); + + // y-axis + svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + // time result + var mean = svg.append("g") + .attr("class", "mean complexity"); + var timeResult = result[Strings.json.controller]; + var yMin = yScale.domain()[0], yMax = yScale.domain()[1]; + this._addRegressionLine(mean, xScale, yScale, [[timeResult.average, yMin], [timeResult.average, yMax]], timeResult.stdev, true); + + // regression + this._addRegression(result[Strings.json.complexity], svg.append("g").attr("class", "regression raw"), xScale, yScale); + this._addRegression(result[Strings.json.complexityAverage], svg.append("g").attr("class", "regression average"), xScale, yScale); + + var bootstrapResult = result[Strings.json.complexity][Strings.json.bootstrap]; + if (bootstrapResult) { + var histogram = d3.layout.histogram() + .bins(xScale.ticks(100))(bootstrapResult.data); + var yBootstrapScale = d3.scale.linear() + .range([size.height/2, 0]) + .domain([0, d3.max(histogram, function(d) { return d.y; })]); + group = svg.append("g").attr("class", "bootstrap"); + var bar = group.selectAll(".bar") + .data(histogram) + .enter().append("g") + .attr("class", "bar") + .attr("transform", function(d) { return "translate(" + xScale(d.x) + "," + yBootstrapScale(d.y) + ")"; }); + bar.append("rect") + .attr("x", 1) + .attr("y", size.height/2) + .attr("width", xScale(histogram[1].x) - xScale(histogram[0].x) - 1) + .attr("height", function(d) { return size.height/2 - yBootstrapScale(d.y); }); + group = group.append("g").attr("class", "median"); + this._addRegressionLine(group, xScale, yScale, [[bootstrapResult.median, yMin], [bootstrapResult.median, yMax]], [bootstrapResult.confidenceLow, bootstrapResult.confidenceHigh], true); + group.append("circle") + .attr("cx", xScale(bootstrapResult.median)) + .attr("cy", yScale(1000/60)) + .attr("r", 5); + } + + // series + group = svg.append("g") + .attr("class", "series raw") + .selectAll("line") + .data(data[Strings.json.complexity]) + .enter(); + group.append("line") + .attr("x1", function(d) { return xScale(d.complexity) - 3; }) + .attr("x2", function(d) { return xScale(d.complexity) + 3; }) + .attr("y1", function(d) { return yScale(d.frameLength) - 3; }) + .attr("y2", function(d) { return yScale(d.frameLength) + 3; }); + group.append("line") + .attr("x1", function(d) { return xScale(d.complexity) - 3; }) + .attr("x2", function(d) { return xScale(d.complexity) + 3; }) + .attr("y1", function(d) { return yScale(d.frameLength) + 3; }) + .attr("y2", function(d) { return yScale(d.frameLength) - 3; }); + + group = svg.append("g") + .attr("class", "series average") + .selectAll("circle") + .data(data[Strings.json.complexityAverage]) + .enter(); + group.append("circle") + .attr("cx", function(d) { return xScale(d.complexity); }) + .attr("cy", function(d) { return yScale(d.frameLength); }) + .attr("r", 3) + group.append("line") + .attr("x1", function(d) { return xScale(d.complexity); }) + .attr("x2", function(d) { return xScale(d.complexity); }) + .attr("y1", function(d) { return yScale(d.frameLength - d.stdev); }) + .attr("y2", function(d) { return yScale(d.frameLength + d.stdev); }); + + // Cursor + var cursorGroup = svg.append("g").attr("class", "cursor hidden"); + cursorGroup.append("line") + .attr("class", "x") + .attr("x1", 0) + .attr("x2", 0) + .attr("y1", yScale(yAxis.scale().domain()[0]) + 10) + .attr("y2", yScale(yAxis.scale().domain()[1])); + cursorGroup.append("line") + .attr("class", "y") + .attr("x1", xScale(xAxis.scale().domain()[0]) - 10) + .attr("x2", xScale(xAxis.scale().domain()[1])) + .attr("y1", 0) + .attr("y2", 0) + cursorGroup.append("text") + .attr("class", "label x") + .attr("x", 0) + .attr("y", yScale(yAxis.scale().domain()[0]) + 15) + .attr("baseline-shift", "-100%") + .attr("text-anchor", "middle"); + cursorGroup.append("text") + .attr("class", "label y") + .attr("x", xScale(xAxis.scale().domain()[0]) - 15) + .attr("y", 0) + .attr("baseline-shift", "-30%") + .attr("text-anchor", "end"); + // Area to handle mouse events + var area = svg.append("rect") + .attr("fill", "transparent") + .attr("x", 0) + .attr("y", 0) + .attr("width", size.width) + .attr("height", size.height); + + area.on("mouseover", function() { + document.querySelector("#complexity-graph .cursor").classList.remove("hidden"); + }).on("mouseout", function() { + document.querySelector("#complexity-graph .cursor").classList.add("hidden"); + }).on("mousemove", function() { + var location = d3.mouse(this); + var location_domain = [xScale.invert(location[0]), yScale.invert(location[1])]; + cursorGroup.select("line.x") + .attr("x1", location[0]) + .attr("x2", location[0]); + cursorGroup.select("text.x") + .attr("x", location[0]) + .text(location_domain[0].toFixed(1)); + cursorGroup.select("line.y") + .attr("y1", location[1]) + .attr("y2", location[1]); + cursorGroup.select("text.y") + .attr("y", location[1]) + .text((1000 / location_domain[1]).toFixed(1)); + }); + }, + + createTimeGraph: function(result, samples, marks, regressions, options, margins, size) + { + var svg = d3.select("#test-graph-data").append("svg") + .attr("id", "time-graph") + .attr("width", size.width + margins.left + margins.right) + .attr("height", size.height + margins.top + margins.bottom) + .append("g") + .attr("transform", "translate(" + margins.left + "," + margins.top + ")"); + + // Axis scales + var x = d3.scale.linear() + .range([0, size.width]) + .domain([ + Math.min(d3.min(samples, function(s) { return s.time; }), 0), + d3.max(samples, function(s) { return s.time; })]); + var complexityMax = d3.max(samples, function(s) { + if (s.time > 0) + return s.complexity; + return 0; + }); + + var yLeft = d3.scale.linear() + .range([size.height, 0]) + .domain([0, complexityMax]); + var yRight = d3.scale.linear() + .range([size.height, 0]) + .domain([1000/20, 1000/60]); + + // Axes + var xAxis = d3.svg.axis() + .scale(x) + .orient("bottom") + .tickFormat(function(d) { return (d/1000).toFixed(0); }); + var yAxisLeft = d3.svg.axis() + .scale(yLeft) + .orient("left"); + var yAxisRight = d3.svg.axis() + .scale(yRight) + .tickValues([1000/20, 1000/25, 1000/30, 1000/35, 1000/40, 1000/45, 1000/50, 1000/55, 1000/60]) + .tickFormat(function(d) { return (1000/d).toFixed(0); }) + .orient("right"); + + // x-axis + svg.append("g") + .attr("class", "x axis") + .attr("fill", "rgb(235, 235, 235)") + .attr("transform", "translate(0," + size.height + ")") + .call(xAxis) + .append("text") + .attr("class", "label") + .attr("x", size.width) + .attr("y", -6) + .attr("fill", "rgb(235, 235, 235)") + .style("text-anchor", "end") + .text("time"); + + // yLeft-axis + svg.append("g") + .attr("class", "yLeft axis") + .attr("fill", "#7ADD49") + .call(yAxisLeft) + .append("text") + .attr("class", "label") + .attr("transform", "rotate(-90)") + .attr("y", 6) + .attr("fill", "#7ADD49") + .attr("dy", ".71em") + .style("text-anchor", "end") + .text(Strings.text.complexity); + + // yRight-axis + svg.append("g") + .attr("class", "yRight axis") + .attr("fill", "#FA4925") + .attr("transform", "translate(" + size.width + ", 0)") + .call(yAxisRight) + .append("text") + .attr("class", "label") + .attr("x", 9) + .attr("y", -20) + .attr("fill", "#FA4925") + .attr("dy", ".71em") + .style("text-anchor", "start") + .text(Strings.text.frameRate); + + // marks + var yMin = yRight(yAxisRight.scale().domain()[0]); + var yMax = yRight(yAxisRight.scale().domain()[1]); + for (var markName in marks) { + var mark = marks[markName]; + var xLocation = x(mark.time); + + var markerGroup = svg.append("g") + .attr("class", "marker") + .attr("transform", "translate(" + xLocation + ", 0)"); + markerGroup.append("text") + .attr("transform", "translate(10, " + (yMin - 10) + ") rotate(-90)") + .style("text-anchor", "start") + .text(markName) + markerGroup.append("line") + .attr("x1", 0) + .attr("x2", 0) + .attr("y1", yMin) + .attr("y2", yMax); + } + + if (Strings.json.controller in result) { + var complexity = result[Strings.json.controller]; + var regression = svg.append("g") + .attr("class", "complexity mean"); + this._addRegressionLine(regression, x, yLeft, [[samples[0].time, complexity.average], [samples[samples.length - 1].time, complexity.average]], complexity.stdev); + } + if (Strings.json.frameLength in result) { + var frameLength = result[Strings.json.frameLength]; + var regression = svg.append("g") + .attr("class", "fps mean"); + this._addRegressionLine(regression, x, yRight, [[samples[0].time, 1000/frameLength.average], [samples[samples.length - 1].time, 1000/frameLength.average]], frameLength.stdev); + } + + // right-target + if (options["controller"] == "adaptive") { + var targetFrameLength = 1000 / options["frame-rate"]; + svg.append("line") + .attr("x1", x(0)) + .attr("x2", size.width) + .attr("y1", yRight(targetFrameLength)) + .attr("y2", yRight(targetFrameLength)) + .attr("class", "target-fps marker"); + } + + // Cursor + var cursorGroup = svg.append("g").attr("class", "cursor"); + cursorGroup.append("line") + .attr("x1", 0) + .attr("x2", 0) + .attr("y1", yMin) + .attr("y2", yMin); + + // Data + var allData = samples; + var filteredData = samples.filter(function (sample) { + return "smoothedFrameLength" in sample; + }); + + function addData(name, data, yCoordinateCallback, pointRadius, omitLine) { + var svgGroup = svg.append("g").attr("id", name); + if (!omitLine) { + svgGroup.append("path") + .datum(data) + .attr("d", d3.svg.line() + .x(function(d) { return x(d.time); }) + .y(yCoordinateCallback)); + } + svgGroup.selectAll("circle") + .data(data) + .enter() + .append("circle") + .attr("cx", function(d) { return x(d.time); }) + .attr("cy", yCoordinateCallback) + .attr("r", pointRadius); + + cursorGroup.append("circle") + .attr("class", name) + .attr("r", pointRadius + 2); + } + + addData("complexity", allData, function(d) { return yLeft(d.complexity); }, 2); + addData("rawFPS", allData, function(d) { return yRight(d.frameLength); }, 1); + addData("filteredFPS", filteredData, function(d) { return yRight(d.smoothedFrameLength); }, 2); + + // regressions + var regressionGroup = svg.append("g") + .attr("id", "regressions"); + if (regressions) { + var complexities = []; + regressions.forEach(function (regression) { + if (!isNaN(regression.segment1[0][1]) && !isNaN(regression.segment1[1][1])) { + regressionGroup.append("line") + .attr("x1", x(regression.segment1[0][0])) + .attr("x2", x(regression.segment1[1][0])) + .attr("y1", yRight(regression.segment1[0][1])) + .attr("y2", yRight(regression.segment1[1][1])); + } + if (!isNaN(regression.segment2[0][1]) && !isNaN(regression.segment2[1][1])) { + regressionGroup.append("line") + .attr("x1", x(regression.segment2[0][0])) + .attr("x2", x(regression.segment2[1][0])) + .attr("y1", yRight(regression.segment2[0][1])) + .attr("y2", yRight(regression.segment2[1][1])); + } + // inflection point + regressionGroup.append("circle") + .attr("cx", x(regression.segment1[1][0])) + .attr("cy", yLeft(regression.complexity)) + .attr("r", 5); + complexities.push(regression.complexity); + }); + if (complexities.length) { + var yLeftComplexities = d3.svg.axis() + .scale(yLeft) + .tickValues(complexities) + .tickSize(10) + .orient("left"); + svg.append("g") + .attr("class", "complexity yLeft axis") + .call(yLeftComplexities); + } + } + + // Area to handle mouse events + var area = svg.append("rect") + .attr("fill", "transparent") + .attr("x", 0) + .attr("y", 0) + .attr("width", size.width) + .attr("height", size.height); + + var timeBisect = d3.bisector(function(d) { return d.time; }).right; + var statsToHighlight = ["complexity", "rawFPS", "filteredFPS"]; + area.on("mouseover", function() { + document.querySelector("#time-graph .cursor").classList.remove("hidden"); + document.querySelector("#test-graph nav").classList.remove("hide-data"); + }).on("mouseout", function() { + document.querySelector("#time-graph .cursor").classList.add("hidden"); + document.querySelector("#test-graph nav").classList.add("hide-data"); + }).on("mousemove", function() { + var form = document.forms["time-graph-options"].elements; + + var mx_domain = x.invert(d3.mouse(this)[0]); + var index = Math.min(timeBisect(allData, mx_domain), allData.length - 1); + var data = allData[index]; + var cursor_x = x(data.time); + var cursor_y = yAxisRight.scale().domain()[1]; + var ys = [yRight(yAxisRight.scale().domain()[0]), yRight(yAxisRight.scale().domain()[1])]; + + document.querySelector("#test-graph nav .time").textContent = (data.time / 1000).toFixed(4) + "s (" + index + ")"; + statsToHighlight.forEach(function(name) { + var element = document.querySelector("#test-graph nav ." + name); + var content = ""; + var data_y = null; + switch (name) { + case "complexity": + content = data.complexity; + data_y = yLeft(data.complexity); + break; + case "rawFPS": + content = (1000/data.frameLength).toFixed(2); + data_y = yRight(data.frameLength); + break; + case "filteredFPS": + if ("smoothedFrameLength" in data) { + content = (1000/data.smoothedFrameLength).toFixed(2); + data_y = yRight(data.smoothedFrameLength); + } + break; + } + + element.textContent = content; + + if (form[name].checked && data_y !== null) { + ys.push(data_y); + cursorGroup.select("." + name) + .attr("cx", cursor_x) + .attr("cy", data_y); + document.querySelector("#time-graph .cursor ." + name).classList.remove("hidden"); + } else + document.querySelector("#time-graph .cursor ." + name).classList.add("hidden"); + }); + + if (form["rawFPS"].checked) + cursor_y = Math.max(cursor_y, data.frameLength); + cursorGroup.select("line") + .attr("x1", cursor_x) + .attr("x2", cursor_x) + .attr("y1", Math.min.apply(null, ys)) + .attr("y2", Math.max.apply(null, ys)); + + }); + }, + + _showOrHideNodes: function(isShown, selector) { + var nodeList = document.querySelectorAll(selector); + if (isShown) { + for (var i = 0; i < nodeList.length; ++i) + nodeList[i].classList.remove("hidden"); + } else { + for (var i = 0; i < nodeList.length; ++i) + nodeList[i].classList.add("hidden"); + } + }, + + onComplexityGraphOptionsChanged: function() { + var form = document.forms["complexity-graph-options"].elements; + benchmarkController._showOrHideNodes(form["series-raw"].checked, "#complexity-graph .series.raw"); + benchmarkController._showOrHideNodes(form["series-average"].checked, "#complexity-graph .series.average"); + benchmarkController._showOrHideNodes(form["regression-time-score"].checked, "#complexity-graph .mean.complexity"); + benchmarkController._showOrHideNodes(form["bootstrap-score"].checked, "#complexity-graph .bootstrap"); + benchmarkController._showOrHideNodes(form["complexity-regression-aggregate-raw"].checked, "#complexity-graph .regression.raw"); + benchmarkController._showOrHideNodes(form["complexity-regression-aggregate-average"].checked, "#complexity-graph .regression.average"); + }, + + onTimeGraphOptionsChanged: function() { + var form = document.forms["time-graph-options"].elements; + benchmarkController._showOrHideNodes(form["markers"].checked, ".marker"); + benchmarkController._showOrHideNodes(form["averages"].checked, "#test-graph-data .mean"); + benchmarkController._showOrHideNodes(form["complexity"].checked, "#complexity"); + benchmarkController._showOrHideNodes(form["rawFPS"].checked, "#rawFPS"); + benchmarkController._showOrHideNodes(form["filteredFPS"].checked, "#filteredFPS"); + benchmarkController._showOrHideNodes(form["regressions"].checked, "#regressions"); + }, + + onGraphTypeChanged: function() { + var form = document.forms["graph-type"].elements; + var testResult = document.getElementById("test-graph-data")._testResult; + var isTimeSelected = form["graph-type"].value == "time"; + + benchmarkController._showOrHideNodes(isTimeSelected, "#time-graph"); + benchmarkController._showOrHideNodes(isTimeSelected, "form[name=time-graph-options]"); + benchmarkController._showOrHideNodes(!isTimeSelected, "#complexity-graph"); + benchmarkController._showOrHideNodes(!isTimeSelected, "form[name=complexity-graph-options]"); + + var score = "", mean = ""; + if (isTimeSelected) { + score = testResult[Strings.json.score].toFixed(2); + + var regression = testResult[Strings.json.controller]; + mean = [ + "mean: ", + regression.average.toFixed(2), + " ± ", + regression.stdev.toFixed(2), + " (", + regression.percent.toFixed(2), + "%)"]; + if (regression.concern) { + mean = mean.concat([ + ", worst 5%: ", + regression.concern.toFixed(2)]); + } + mean = mean.join(""); + } else { + var complexityRegression = testResult[Strings.json.complexity]; + var complexityAverageRegression = testResult[Strings.json.complexityAverage]; + + document.getElementById("complexity-regression-aggregate-raw").textContent = complexityRegression.complexity.toFixed(2) + ", ±" + complexityRegression.stdev.toFixed(2) + "ms"; + document.getElementById("complexity-regression-aggregate-average").textContent = complexityAverageRegression.complexity.toFixed(2) + ", ±" + complexityAverageRegression.stdev.toFixed(2) + "ms"; + + var bootstrap = complexityRegression[Strings.json.bootstrap]; + if (bootstrap) { + score = bootstrap.median.toFixed(2); + mean = [ + (bootstrap.confidencePercentage * 100).toFixed(0), + "% CI: ", + bootstrap.confidenceLow.toFixed(2), + "–", + bootstrap.confidenceHigh.toFixed(2) + ].join(""); + } + } + + sectionsManager.setSectionScore("test-graph", score, mean); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/tests.js b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/tests.js new file mode 100644 index 0000000000..accaa3c3df --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/tests.js @@ -0,0 +1,345 @@ +Utilities.extendObject(Strings.text, { + samples: "Samples", + complexity: "Time Complexity", + frameRate: "FPS", + confidenceInterval: "80% Confidence Interval", + mergedRawComplexity: "Raw Complexity", + graph: "Graph" +}); + + +Utilities.extendObject(Headers, { + details: [ + { + title: Strings.text.graph + }, + { + title: Strings.text.confidenceInterval, + children: + [ + { + text: function(data) { + return data[Strings.json.complexity][Strings.json.bootstrap].confidenceLow.toFixed(2); + }, + className: "right pad-left pad-right" + }, + { + text: function(data) { + return " - " + data[Strings.json.complexity][Strings.json.bootstrap].confidenceHigh.toFixed(2); + }, + className: "left" + }, + { + text: function(data) { + var bootstrap = data[Strings.json.complexity][Strings.json.bootstrap]; + return (100 * (bootstrap.confidenceLow / bootstrap.median - 1)).toFixed(2) + "%"; + }, + className: "left pad-left small" + }, + { + text: function(data) { + var bootstrap = data[Strings.json.complexity][Strings.json.bootstrap]; + return "+" + (100 * (bootstrap.confidenceHigh / bootstrap.median - 1)).toFixed(2) + "%"; + }, + className: "left pad-left small" + } + ] + }, + { + title: Strings.text.complexity, + children: + [ + { + text: function(data) { + return data[Strings.json.controller][Strings.json.measurements.average].toFixed(2); + }, + className: "average" + }, + { + text: function(data) { + return [ + "± ", + data[Strings.json.controller][Strings.json.measurements.percent].toFixed(2), + "%" + ].join(""); + }, + className: function(data) { + var className = "stdev"; + + if (data[Strings.json.controller][Strings.json.measurements.percent] >= 10) + className += " noisy-results"; + return className; + } + } + ] + }, + { + title: Strings.text.frameRate, + children: + [ + { + text: function(data) { + return data[Strings.json.frameLength][Strings.json.measurements.average].toFixed(2); + }, + className: function(data, options) { + var className = "average"; + if (Math.abs(data[Strings.json.frameLength][Strings.json.measurements.average] - options["frame-rate"]) >= 2) + className += " noisy-results"; + return className; + } + }, + { + text: function(data) { + var frameRateData = data[Strings.json.frameLength]; + return [ + "± ", + frameRateData[Strings.json.measurements.percent].toFixed(2), + "%" + ].join(""); + }, + className: function(data) { + var className = "stdev"; + + if (data[Strings.json.frameLength][Strings.json.measurements.percent] >= 10) + className += " noisy-results"; + return className; + } + } + ] + }, + { + title: Strings.text.mergedRawComplexity, + children: + [ + { + text: function(data) { + return data[Strings.json.complexity][Strings.json.complexity].toFixed(2); + }, + className: "average" + }, + { + text: function(data) { + return [ + "± ", + data[Strings.json.complexity][Strings.json.measurements.stdev].toFixed(2), + "ms" + ].join(""); + }, + className: "stdev" + } + ] + } + ] +}) + +/////////// +// Suites + +Suites.push(new Suite("HTML suite", + [ + { + url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=12&particleHeight=12&shape=circle", + name: "CSS bouncing circles" + }, + { + url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=40&particleHeight=40&shape=rect&clip=star", + name: "CSS bouncing clipped rects" + }, + { + url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=50&particleHeight=50&shape=circle&fill=gradient", + name: "CSS bouncing gradient circles" + }, + { + url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=80&particleHeight=80&shape=circle&blend", + name: "CSS bouncing blend circles" + }, + { + url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=80&particleHeight=80&shape=circle&filter", + name: "CSS bouncing filter circles" + }, + { + url: "bouncing-particles/bouncing-css-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.svg", + name: "CSS bouncing SVG images" + }, + { + url: "bouncing-particles/bouncing-tagged-images.html?particleWidth=100&particleHeight=100", + name: "CSS bouncing tagged images" + }, + { + url: "dom/leaves.html", + name: "Leaves 2.0" + }, + { + url: "dom/focus.html", + name: "Focus 2.0" + }, + { + url: "dom/particles.html", + name: "DOM particles, SVG masks" + }, + { + url: "dom/compositing-transforms.html?particleWidth=50&particleHeight=50&filters=yes&imageSrc=../resources/yin-yang.svg", + name: "Composited Transforms" + } + ] +)); + +Suites.push(new Suite("Canvas suite", + [ + { + url: "bouncing-particles/bouncing-canvas-shapes.html?particleWidth=40&particleHeight=40&shape=rect&clip=star", + name: "canvas bouncing clipped rects" + }, + { + url: "bouncing-particles/bouncing-canvas-shapes.html?particleWidth=50&particleHeight=50&shape=circle&fill=gradient", + name: "canvas bouncing gradient circles" + }, + { + url: "bouncing-particles/bouncing-canvas-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.svg", + name: "canvas bouncing SVG images" + }, + { + url: "bouncing-particles/bouncing-canvas-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.png", + name: "canvas bouncing PNG images" + }, + { + url: "simple/simple-canvas-paths.html?pathType=strokes", + name: "Stroke shapes" + }, + { + url: "simple/simple-canvas-paths.html?pathType=fills", + name: "Fill shapes" + }, + { + url: "simple/tiled-canvas-image.html", + name: "Canvas put/get image data" + }, + ] +)); + +Suites.push(new Suite("SVG suite", + [ + { + url: "bouncing-particles/bouncing-svg-shapes.html?particleWidth=12&particleHeight=12&shape=circle", + name: "SVG bouncing circles", + }, + { + url: "bouncing-particles/bouncing-svg-shapes.html?particleWidth=40&particleHeight=40&shape=rect&clip=star", + name: "SVG bouncing clipped rects", + }, + { + url: "bouncing-particles/bouncing-svg-shapes.html?particleWidth=50&particleHeight=50&shape=circle&fill=gradient", + name: "SVG bouncing gradient circles" + }, + { + url: "bouncing-particles/bouncing-svg-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.svg", + name: "SVG bouncing SVG images" + }, + { + url: "bouncing-particles/bouncing-svg-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.png", + name: "SVG bouncing PNG images" + }, + ] +)); + +Suites.push(new Suite("3D Graphics", + [ + { + url: "3d/webgl.html", + name: "WebGL" + }, + ] +)); + +Suites.push(new Suite("Basic canvas path suite", + [ + { + url: "simple/simple-canvas-paths.html?pathType=line&lineCap=butt", + name: "Canvas line segments, butt caps" + }, + { + url: "simple/simple-canvas-paths.html?pathType=line&lineCap=round", + name: "Canvas line segments, round caps" + }, + { + url: "simple/simple-canvas-paths.html?pathType=line&lineCap=square", + name: "Canvas line segments, square caps" + }, + { + url: "simple/simple-canvas-paths.html?pathType=linePath&lineJoin=bevel", + name: "Canvas line path, bevel join" + }, + { + url: "simple/simple-canvas-paths.html?pathType=linePath&lineJoin=round", + name: "Canvas line path, round join" + }, + { + url: "simple/simple-canvas-paths.html?pathType=linePath&lineJoin=miter", + name: "Canvas line path, miter join" + }, + { + url: "simple/simple-canvas-paths.html?pathType=linePath&lineDash=1", + name: "Canvas line path with dash pattern" + }, + { + url: "simple/simple-canvas-paths.html?pathType=quadratic", + name: "Canvas quadratic segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=quadraticPath", + name: "Canvas quadratic path" + }, + { + url: "simple/simple-canvas-paths.html?pathType=bezier", + name: "Canvas bezier segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=bezierPath", + name: "Canvas bezier path" + }, + { + url: "simple/simple-canvas-paths.html?&pathType=arcTo", + name: "Canvas arcTo segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=arc", + name: "Canvas arc segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=rect", + name: "Canvas rects" + }, + { + url: "simple/simple-canvas-paths.html?pathType=ellipse", + name: "Canvas ellipses" + }, + { + url: "simple/simple-canvas-paths.html?pathType=lineFill", + name: "Canvas line path, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=quadraticFill", + name: "Canvas quadratic path, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=bezierFill", + name: "Canvas bezier path, fill" + }, + { + url: "simple/simple-canvas-paths.html?&pathType=arcToFill", + name: "Canvas arcTo segments, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=arcFill", + name: "Canvas arc segments, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=rectFill", + name: "Canvas rects, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=ellipseFill", + name: "Canvas ellipses, fill" + } + ] +)); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/extensions.js b/third_party/webkit/PerformanceTests/MotionMark/resources/extensions.js new file mode 100644 index 0000000000..fb9d500877 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/extensions.js @@ -0,0 +1,670 @@ +Utilities = +{ + _parse: function(str, sep) + { + var output = {}; + str.split(sep).forEach(function(part) { + var item = part.split("="); + var value = decodeURIComponent(item[1]); + if (value[0] == "'" ) + output[item[0]] = value.substr(1, value.length - 2); + else + output[item[0]] = value; + }); + return output; + }, + + parseParameters: function() + { + return this._parse(window.location.search.substr(1), "&"); + }, + + parseArguments: function(str) + { + return this._parse(str, " "); + }, + + extendObject: function(obj1, obj2) + { + for (var attrname in obj2) + obj1[attrname] = obj2[attrname]; + return obj1; + }, + + copyObject: function(obj) + { + return this.extendObject({}, obj); + }, + + mergeObjects: function(obj1, obj2) + { + return this.extendObject(this.copyObject(obj1), obj2); + }, + + createClass: function(classConstructor, classMethods) + { + classConstructor.prototype = classMethods; + return classConstructor; + }, + + createSubclass: function(superclass, classConstructor, classMethods) + { + classConstructor.prototype = Object.create(superclass.prototype); + classConstructor.prototype.constructor = classConstructor; + if (classMethods) + Utilities.extendObject(classConstructor.prototype, classMethods); + return classConstructor; + }, + + createElement: function(name, attrs, parentElement) + { + var element = document.createElement(name); + + for (var key in attrs) + element.setAttribute(key, attrs[key]); + + parentElement.appendChild(element); + return element; + }, + + createSVGElement: function(name, attrs, xlinkAttrs, parentElement) + { + const svgNamespace = "http://www.w3.org/2000/svg"; + const xlinkNamespace = "http://www.w3.org/1999/xlink"; + + var element = document.createElementNS(svgNamespace, name); + + for (var key in attrs) + element.setAttribute(key, attrs[key]); + + for (var key in xlinkAttrs) + element.setAttributeNS(xlinkNamespace, key, xlinkAttrs[key]); + + parentElement.appendChild(element); + return element; + }, + + browserPrefix: function() + { + // Get the HTML element's CSSStyleDeclaration + var styles = window.getComputedStyle(document.documentElement, ''); + + // Convert the styles list to an array + var stylesArray = Array.prototype.slice.call(styles); + + // Concatenate all the styles in one big string + var stylesString = stylesArray.join(''); + + // Search the styles string for a known prefix type, settle on Opera if none is found. + var prefixes = stylesString.match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']); + + // prefixes has two elements; e.g. for webkit it has ['-webkit-', 'webkit']; + var prefix = prefixes[1]; + + // Have 'O' before 'Moz' in the string so it is matched first. + var dom = ('WebKit|O|Moz|MS').match(new RegExp(prefix, 'i'))[0]; + + // Return all the required prefixes. + return { + dom: dom, + lowercase: prefix, + css: '-' + prefix + '-', + js: prefix[0].toUpperCase() + prefix.substr(1) + }; + }, + + setElementPrefixedProperty: function(element, property, value) + { + element.style[property] = element.style[this.browserPrefix().js + property[0].toUpperCase() + property.substr(1)] = value; + }, + + stripNonASCIICharacters: function(inputString) + { + return inputString.replace(/[ .,]/g, ''); + }, + + convertObjectToQueryString: function(object) + { + var queryString = []; + for (var property in object) { + if (object.hasOwnProperty(property)) + queryString.push(encodeURIComponent(property) + "=" + encodeURIComponent(object[property])); + } + return "?" + queryString.join("&"); + }, + + convertQueryStringToObject: function(queryString) + { + queryString = queryString.substring(1); + if (!queryString) + return null; + + var object = {}; + queryString.split("&").forEach(function(parameter) { + var components = parameter.split("="); + object[components[0]] = components[1]; + }); + return object; + }, + + progressValue: function(value, min, max) + { + return (value - min) / (max - min); + }, + + lerp: function(value, min, max) + { + return min + (max - min) * value; + }, + + toFixedNumber: function(number, precision) + { + if (number.toFixed) + return Number(number.toFixed(precision)); + return number; + } +}; + +Array.prototype.swap = function(i, j) +{ + var t = this[i]; + this[i] = this[j]; + this[j] = t; + return this; +} + +if (!Array.prototype.fill) { + Array.prototype.fill = function(value) { + if (this == null) + throw new TypeError('Array.prototype.fill called on null or undefined'); + + var object = Object(this); + var len = parseInt(object.length, 10); + var start = arguments[1]; + var relativeStart = parseInt(start, 10) || 0; + var k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len); + var end = arguments[2]; + var relativeEnd = end === undefined ? len : (parseInt(end) || 0) ; + var final = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len); + + for (; k < final; k++) + object[k] = value; + + return object; + }; +} + +if (!Array.prototype.find) { + Array.prototype.find = function(predicate) { + if (this == null) + throw new TypeError('Array.prototype.find called on null or undefined'); + if (typeof predicate !== 'function') + throw new TypeError('predicate must be a function'); + + var list = Object(this); + var length = list.length >>> 0; + var thisArg = arguments[1]; + var value; + + for (var i = 0; i < length; i++) { + value = list[i]; + if (predicate.call(thisArg, value, i, list)) + return value; + } + return undefined; + }; +} + +Array.prototype.shuffle = function() +{ + for (var index = this.length - 1; index >= 0; --index) { + var randomIndex = Math.floor(Math.random() * (index + 1)); + this.swap(index, randomIndex); + } + return this; +} + +Point = Utilities.createClass( + function(x, y) + { + this.x = x; + this.y = y; + }, { + + // Used when the point object is used as a size object. + get width() + { + return this.x; + }, + + // Used when the point object is used as a size object. + get height() + { + return this.y; + }, + + // Used when the point object is used as a size object. + get center() + { + return new Point(this.x / 2, this.y / 2); + }, + + str: function() + { + return "x = " + this.x + ", y = " + this.y; + }, + + add: function(other) + { + if(isNaN(other.x)) + return new Point(this.x + other, this.y + other); + return new Point(this.x + other.x, this.y + other.y); + }, + + subtract: function(other) + { + if(isNaN(other.x)) + return new Point(this.x - other, this.y - other); + return new Point(this.x - other.x, this.y - other.y); + }, + + multiply: function(other) + { + if(isNaN(other.x)) + return new Point(this.x * other, this.y * other); + return new Point(this.x * other.x, this.y * other.y); + }, + + move: function(angle, velocity, timeDelta) + { + return this.add(Point.pointOnCircle(angle, velocity * (timeDelta / 1000))); + }, + + length: function() { + return Math.sqrt( this.x * this.x + this.y * this.y ); + }, + + normalize: function() { + var l = Math.sqrt( this.x * this.x + this.y * this.y ); + this.x /= l; + this.y /= l; + return this; + } +}); + +Utilities.extendObject(Point, { + zero: new Point(0, 0), + + pointOnCircle: function(angle, radius) + { + return new Point(radius * Math.cos(angle), radius * Math.sin(angle)); + }, + + pointOnEllipse: function(angle, radiuses) + { + return new Point(radiuses.x * Math.cos(angle), radiuses.y * Math.sin(angle)); + }, + + elementClientSize: function(element) + { + var rect = element.getBoundingClientRect(); + return new Point(rect.width, rect.height); + } +}); + +Insets = Utilities.createClass( + function(top, right, bottom, left) + { + this.top = top; + this.right = right; + this.bottom = bottom; + this.left = left; + }, { + + get width() + { + return this.left + this.right; + }, + + get height() + { + return this.top + this.bottom; + }, + + get size() + { + return new Point(this.width, this.height); + } +}); + +Insets.elementPadding = function(element) +{ + var styles = window.getComputedStyle(element); + return new Insets( + parseFloat(styles.paddingTop), + parseFloat(styles.paddingRight), + parseFloat(styles.paddingBottom), + parseFloat(styles.paddingTop)); +} + +UnitBezier = Utilities.createClass( + function(point1, point2) + { + // First and last points in the Bézier curve are assumed to be (0,0) and (!,1) + this._c = point1.multiply(3); + this._b = point2.subtract(point1).multiply(3).subtract(this._c); + this._a = new Point(1, 1).subtract(this._c).subtract(this._b); + }, { + + epsilon: 1e-5, + derivativeEpsilon: 1e-6, + + solve: function(x) + { + return this.sampleY(this.solveForT(x)); + }, + + sampleX: function(t) + { + return ((this._a.x * t + this._b.x) * t + this._c.x) * t; + }, + + sampleY: function(t) + { + return ((this._a.y * t + this._b.y) * t + this._c.y) * t; + }, + + sampleDerivativeX: function(t) + { + return(3 * this._a.x * t + 2 * this._b.x) * t + this._c.x; + }, + + solveForT: function(x) + { + var t0, t1, t2, x2, d2, i; + + for (t2 = x, i = 0; i < 8; ++i) { + x2 = this.sampleX(t2) - x; + if (Math.abs(x2) < this.epsilon) + return t2; + d2 = this.sampleDerivativeX(t2); + if (Math.abs(d2) < this.derivativeEpsilon) + break; + t2 = t2 - x2 / d2; + } + + t0 = 0; + t1 = 1; + t2 = x; + + if (t2 < t0) + return t0; + if (t2 > t1) + return t1; + + while (t0 < t1) { + x2 = this.sampleX(t2); + if (Math.abs(x2 - x) < this.epsilon) + return t2; + if (x > x2) + t0 = t2; + else + t1 = t2; + t2 = (t1 - t0) * .5 + t0; + } + + return t2; + } +}); + +SimplePromise = Utilities.createClass( + function() + { + this._chainedPromise = null; + this._callback = null; + }, { + + then: function (callback) + { + if (this._callback) + throw "SimplePromise doesn't support multiple calls to then"; + + this._callback = callback; + this._chainedPromise = new SimplePromise; + + if (this._resolved) + this.resolve(this._resolvedValue); + + return this._chainedPromise; + }, + + resolve: function (value) + { + if (!this._callback) { + this._resolved = true; + this._resolvedValue = value; + return; + } + + var result = this._callback(value); + if (result instanceof SimplePromise) { + var chainedPromise = this._chainedPromise; + result.then(function (result) { chainedPromise.resolve(result); }); + } else + this._chainedPromise.resolve(result); + } +}); + +var Heap = Utilities.createClass( + function(maxSize, compare) + { + this._maxSize = maxSize; + this._compare = compare; + this._size = 0; + this._values = new Array(this._maxSize); + }, { + + // This is a binary heap represented in an array. The root element is stored + // in the first element in the array. The root is followed by its two children. + // Then its four grandchildren and so on. So every level in the binary heap is + // doubled in the following level. Here is an example of the node indices and + // how they are related to their parents and children. + // =========================================================================== + // 0 1 2 3 4 5 6 + // PARENT -1 0 0 1 1 2 2 + // LEFT 1 3 5 7 9 11 13 + // RIGHT 2 4 6 8 10 12 14 + // =========================================================================== + _parentIndex: function(i) + { + return i > 0 ? Math.floor((i - 1) / 2) : -1; + }, + + _leftIndex: function(i) + { + var leftIndex = i * 2 + 1; + return leftIndex < this._size ? leftIndex : -1; + }, + + _rightIndex: function(i) + { + var rightIndex = i * 2 + 2; + return rightIndex < this._size ? rightIndex : -1; + }, + + // Return the child index that may violate the heap property at index i. + _childIndex: function(i) + { + var left = this._leftIndex(i); + var right = this._rightIndex(i); + + if (left != -1 && right != -1) + return this._compare(this._values[left], this._values[right]) > 0 ? left : right; + + return left != -1 ? left : right; + }, + + init: function() + { + this._size = 0; + }, + + top: function() + { + return this._size ? this._values[0] : NaN; + }, + + push: function(value) + { + if (this._size == this._maxSize) { + // If size is bounded and the new value can be a parent of the top() + // if the size were unbounded, just ignore the new value. + if (this._compare(value, this.top()) > 0) + return; + this.pop(); + } + this._values[this._size++] = value; + this._bubble(this._size - 1); + }, + + pop: function() + { + if (!this._size) + return NaN; + + this._values[0] = this._values[--this._size]; + this._sink(0); + }, + + _bubble: function(i) + { + // Fix the heap property at index i given that parent is the only node that + // may violate the heap property. + for (var pi = this._parentIndex(i); pi != -1; i = pi, pi = this._parentIndex(pi)) { + if (this._compare(this._values[pi], this._values[i]) > 0) + break; + + this._values.swap(pi, i); + } + }, + + _sink: function(i) + { + // Fix the heap property at index i given that each of the left and the right + // sub-trees satisfies the heap property. + for (var ci = this._childIndex(i); ci != -1; i = ci, ci = this._childIndex(ci)) { + if (this._compare(this._values[i], this._values[ci]) > 0) + break; + + this._values.swap(ci, i); + } + }, + + str: function() + { + var out = "Heap[" + this._size + "] = ["; + for (var i = 0; i < this._size; ++i) { + out += this._values[i]; + if (i < this._size - 1) + out += ", "; + } + return out + "]"; + }, + + values: function(size) { + // Return the last "size" heap elements values. + var values = this._values.slice(0, this._size); + return values.sort(this._compare).slice(0, Math.min(size, this._size)); + } +}); + +Utilities.extendObject(Heap, { + createMinHeap: function(maxSize) + { + return new Heap(maxSize, function(a, b) { return b - a; }); + }, + + createMaxHeap: function(maxSize) { + return new Heap(maxSize, function(a, b) { return a - b; }); + } +}); + +var SampleData = Utilities.createClass( + function(fieldMap, data) + { + this.fieldMap = fieldMap || {}; + this.data = data || []; + }, { + + get length() + { + return this.data.length; + }, + + addField: function(name, index) + { + this.fieldMap[name] = index; + }, + + push: function(datum) + { + this.data.push(datum); + }, + + sort: function(sortFunction) + { + this.data.sort(sortFunction); + }, + + slice: function(begin, end) + { + return new SampleData(this.fieldMap, this.data.slice(begin, end)); + }, + + forEach: function(iterationFunction) + { + this.data.forEach(iterationFunction); + }, + + createDatum: function() + { + return []; + }, + + getFieldInDatum: function(datum, fieldName) + { + if (typeof datum === 'number') + datum = this.data[datum]; + return datum[this.fieldMap[fieldName]]; + }, + + setFieldInDatum: function(datum, fieldName, value) + { + if (typeof datum === 'number') + datum = this.data[datum]; + return datum[this.fieldMap[fieldName]] = value; + }, + + at: function(index) + { + return this.data[index]; + }, + + toArray: function() + { + var array = []; + + this.data.forEach(function(datum) { + var newDatum = {}; + array.push(newDatum); + + for (var fieldName in this.fieldMap) { + var value = this.getFieldInDatum(datum, fieldName); + if (value !== null && value !== undefined) + newDatum[fieldName] = value; + } + }, this); + + return array; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css new file mode 100644 index 0000000000..86da6bea1c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css @@ -0,0 +1,520 @@ +/* Outer harness */ + +html, +body { + min-height: 100%; +} + +body { + background-color: hsl(0, 0%, 95%); + + font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif; + font-size: 15px; + + cursor: default; + + -webkit-user-select: none; +} + +body.showing-intro, +body.showing-results { + background-color: hsl(35, 100%, 100%); + background-image: url(crystal.svg), url(lines.svg); + background-size: auto 225%, auto 100%; + background-repeat: no-repeat; + + animation: background-fade 1s ease-in 1s, background-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: background-color; +} + +body.showing-test-container { + overflow: hidden; +} + +body.images-loaded { + animation-play-state: running; +} + +@media screen and (min-width: 667px) { + body { + font-size: 24px; + } + + body.showing-intro, + body.showing-results { + background-size: 200% 100%, 150% auto; + } +} + +@media screen and (min-width: 1025px) { + body.showing-intro, + body.showing-results { + background-size: 150% 100%, 150% auto; + } +} + +::selection { + background-color: black; + color: white; +} + +.hidden { + display: none; +} + +section { + display: none; +} + +section.selected { + display: block; +} + +svg.logo { + width: 350px; + height: 88px; + + max-width: 100%; + + padding-bottom: 1em; + + color: hsl(35, 100%, 50%); + + animation: foreground-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: color; +} + +body.images-loaded svg.logo { + animation-play-state: running; +} + +@media screen and (min-width: 667px) { + svg.logo { + width: 525px; + height: 130px; + } +} + +section .body { + margin: 0 1em; + max-width: 350px; +} + +section .body p { + margin: 1em 0; + line-height: 1.5em; + + -webkit-user-select: text; + cursor: text; +} + +@media screen and (min-width: 667px) { + section .body { + margin-left: 2.5em; + max-width: 500px; + transform: skewX(-10deg); + } + + section button { + transform: none; + } +} + +button { + background-color: hsl(35, 100%, 50%); + color: white; + + padding: 0.25em; + margin: 1.5em -0.25em 0 0; + + min-width: 50%; + + border: none; + + font-family: inherit; + font-size: inherit; + + transform: skewX(-10deg); + + transition: 100ms filter ease-in-out; + + animation: background-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: background-color; +} + +body.images-loaded button { + animation-play-state: running; +} + +button:hover { + filter: brightness(115%); +} + +button:active { + filter: brightness(130%); +} + +button:disabled { + opacity: 0.5; + filter: none !important; +} + +@media print { + button { + display: none; + } +} + +.portrait-orientation-check { + display: none; +} + +@media screen and (max-device-width: 1025px) and (orientation: portrait) { + .portrait-orientation-check { + display: block; + } +} + +@media screen and (max-device-width: 1025px) and (orientation: portrait) { + .landscape-orientation-check { + /* This keeps the button color animation in sync with page, while display: none does not. */ + visibility: hidden; + } +} + +@keyframes background-fade { + 100% { + background-color: hsl(35, 100%, 50%); + } +} + +@keyframes background-color { + 0%, 10% { + background-color: hsl(35, 100%, 50%); + } + + 12%, 20% { + background-color: hsl(75, 100%, 30%); + } + + 22%, 30% { + background-color: hsl(115, 100%, 30%); + } + + 32%, 40% { + background-color: hsl(155, 100%, 30%); + } + + 42%, 50% { + background-color: hsl(195, 100%, 30%); + } + + 52%, 60% { + background-color: hsl(235, 100%, 30%); + } + + 62%, 70% { + background-color: hsl(275, 100%, 30%); + } + + 72%, 80% { + background-color: hsl(315, 100%, 30%); + } + + 82%, 90% { + background-color: hsl(355, 100%, 30%); + } + + 92%, 100% { + background-color: hsl(395, 100%, 50%); + } +} + +@keyframes foreground-color { + 0%, 10% { + color: hsl(35, 100%, 50%); + } + + 12%, 20% { + color: hsl(75, 100%, 30%); + } + + 22%, 30% { + color: hsl(115, 100%, 30%); + } + + 32%, 40% { + color: hsl(155, 100%, 30%); + } + + 42%, 50% { + color: hsl(195, 100%, 30%); + } + + 52%, 60% { + color: hsl(235, 100%, 30%); + } + + 62%, 70% { + color: hsl(275, 100%, 30%); + } + + 72%, 80% { + color: hsl(315, 100%, 30%); + } + + 82%, 90% { + color: hsl(355, 100%, 30%); + } + + 92%, 100% { + color: hsl(395, 100%, 50%); + } +} + +/* Intro section, About page */ + +#intro, #about { + padding: 2em; +} + +#intro { + opacity: 0; + transition: opacity 500ms ease-in; +} + +body.images-loaded #intro { + opacity: 1; +} + +#about .body { + transform: none; + margin: 0; + max-width: initial; +} + +#about li { + line-height: 1.5em; +} + +#about button { + padding: .75em 2em; + margin: 1.5em auto 0; + min-width: initial; + transform: skewX(-10deg); +} + +@media screen and (min-width: 667px) { + #about .body { + font-size: .7em; + margin: 1em; + } + + #about ol, #about ul { + padding-left: 3em; + } +} + + +#intro a, #about a, +#intro a:visited, #about a:visited { + color: black; +} + +/* Running test section */ + +.frame-container { + position: absolute; + + top: 50%; + left: 50%; +} + +.frame-container > iframe { + width: 100%; + height: 100%; + + border: 0; + margin: 0; +} + +body.small .frame-container { + width: 568px; + height: 320px; + margin-left: -284px; + margin-top: -160px; +} + +body.medium .frame-container { + width: 900px; + height: 600px; + margin-left: -450px; + margin-top: -300px; +} + +body.large .frame-container { + width: 1600px; + height: 800px; + margin-left: -800px; + margin-top: -400px; +} + +/* Results section */ + +#results { + padding: 2em; +} + +#results .body { + -webkit-user-select: text; +} + +#results .score-container { + padding-bottom: 2em; +} + +#results .table-container { + position: relative; +} + +#results .table-container > div { + margin-left: 40%; +} + +#results .score { + font-size: 5em; + font-weight: bold; + font-style: italic; + line-height: 1; + margin: 0; +} + +#results .confidence { + font-size: 2em; + font-style: italic; + line-height: 1; + margin: 0; + text-indent: 1.75em; + color: hsl(0, 0%, 40%); + padding-bottom: .3em; +} + +#results table { + border-spacing: 0; + margin: 0; + padding: 0; + min-width: 25%; +} + +#results table td, +#results table th { + padding: 0.25em; +} + +#results table td.suites-separator { + padding: 0; +} + +#results table tr:nth-child(even) { + background-color: hsla(0, 0%, 0%, 0.05); +} + +#results #results-header { + top: 0; + left: 0; + width: 40%; + position: absolute; +} + +#results #results-score { + float: left; +} + +#results #results-data span { + font-size: .75em; + color: hsl(0, 0%, 40%); +} + +#results #results-header td, +#results #results-header th { + text-align: right; + padding-right: 1em !important; + padding-left: 0.5em !important; +} + +#results #results-score td, +#results #results-score th { + text-align: left; + padding-right: 0.5em !important; +} + +#results #results-score td { + cursor: text; +} + +@media screen and (min-width: 667px) { + #results .score, + #results .confidence { + font-style: normal; + } +} + +.detail span { + display: none; +} + +body.small .detail .small, +body.medium .detail .medium, +body.large .detail .large { + display: initial; +} + +#overlay { + position: fixed; + + top: 0; + left: 0; + bottom: 0; + right: 0; + + background: hsla(0, 0%, 100%, 0.9); +} + +@supports (-webkit-backdrop-filter: blur(10px)) { + #overlay { + background: hsla(0, 0%, 100%, 0.7); + -webkit-backdrop-filter: blur(20px); + } +} + +#overlay > div { + position: absolute; + + width: 500px; + height: 500px; + + margin-top: -250px; + margin-left: -250px; + + top: 50%; + left: 50%; +} + +#overlay > div div { + overflow: scroll; + + font-size: 12px; + -webkit-user-select: text; + cursor: text; + + max-height: 250px; + + border: 1px solid hsla(0, 0%, 0%, 0.1); + padding: 1em; +} diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js new file mode 100644 index 0000000000..65e8c5450d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js @@ -0,0 +1,626 @@ +ResultsDashboard = Utilities.createClass( + function(options, testData) + { + this._iterationsSamplers = []; + this._options = options; + this._results = null; + if (testData) { + this._iterationsSamplers = testData; + this._processData(); + } + }, { + + push: function(suitesSamplers) + { + this._iterationsSamplers.push(suitesSamplers); + }, + + _processData: function() + { + this._results = {}; + this._results[Strings.json.results.iterations] = []; + + var iterationsScores = []; + this._iterationsSamplers.forEach(function(iteration, index) { + var testsScores = []; + var testsLowerBoundScores = []; + var testsUpperBoundScores = []; + + var result = {}; + this._results[Strings.json.results.iterations][index] = result; + + var suitesResult = {}; + result[Strings.json.results.tests] = suitesResult; + + for (var suiteName in iteration) { + var suiteData = iteration[suiteName]; + + var suiteResult = {}; + suitesResult[suiteName] = suiteResult; + + for (var testName in suiteData) { + if (!suiteData[testName][Strings.json.result]) + this.calculateScore(suiteData[testName]); + + suiteResult[testName] = suiteData[testName][Strings.json.result]; + delete suiteData[testName][Strings.json.result]; + + testsScores.push(suiteResult[testName][Strings.json.score]); + testsLowerBoundScores.push(suiteResult[testName][Strings.json.scoreLowerBound]); + testsUpperBoundScores.push(suiteResult[testName][Strings.json.scoreUpperBound]); + } + } + + result[Strings.json.score] = Statistics.geometricMean(testsScores); + result[Strings.json.scoreLowerBound] = Statistics.geometricMean(testsLowerBoundScores); + result[Strings.json.scoreUpperBound] = Statistics.geometricMean(testsUpperBoundScores); + iterationsScores.push(result[Strings.json.score]); + }, this); + + this._results[Strings.json.score] = Statistics.sampleMean(iterationsScores.length, iterationsScores.reduce(function(a, b) { return a + b; })); + this._results[Strings.json.scoreLowerBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreLowerBound]; + this._results[Strings.json.scoreUpperBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreUpperBound]; + }, + + calculateScore: function(data) + { + var result = {}; + data[Strings.json.result] = result; + var samples = data[Strings.json.samples]; + + var desiredFrameLength = 1000/60; + if (this._options["controller"] == "ramp30") + desiredFrameLength = 1000/30; + + function findRegression(series, profile) { + var minIndex = Math.round(.025 * series.length); + var maxIndex = Math.round(.975 * (series.length - 1)); + var minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity); + var maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity); + + if (Math.abs(maxComplexity - minComplexity) < 20 && maxIndex - minIndex < 20) { + minIndex = 0; + maxIndex = series.length - 1; + minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity); + maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity); + } + + var complexityIndex = series.fieldMap[Strings.json.complexity]; + var frameLengthIndex = series.fieldMap[Strings.json.frameLength]; + var regressionOptions = { desiredFrameLength: desiredFrameLength }; + if (profile) + regressionOptions.preferredProfile = profile; + return { + minComplexity: minComplexity, + maxComplexity: maxComplexity, + samples: series.slice(minIndex, maxIndex + 1), + regression: new Regression( + series.data, + function (data, i) { return data[i][complexityIndex]; }, + function (data, i) { return data[i][frameLengthIndex]; }, + minIndex, maxIndex, regressionOptions) + }; + } + + var complexitySamples; + // Convert these samples into SampleData objects if needed + [Strings.json.complexity, Strings.json.complexityAverage, Strings.json.controller].forEach(function(seriesName) { + var series = samples[seriesName]; + if (series && !(series instanceof SampleData)) + samples[seriesName] = new SampleData(series.fieldMap, series.data); + }); + + var isRampController = ["ramp", "ramp30"].indexOf(this._options["controller"]) != -1; + var predominantProfile = ""; + if (isRampController) { + var profiles = {}; + data[Strings.json.controller].forEach(function(regression) { + if (regression[Strings.json.regressions.profile]) { + var profile = regression[Strings.json.regressions.profile]; + profiles[profile] = (profiles[profile] || 0) + 1; + } + }); + + var maxProfileCount = 0; + for (var profile in profiles) { + if (profiles[profile] > maxProfileCount) { + predominantProfile = profile; + maxProfileCount = profiles[profile]; + } + } + } + + [Strings.json.complexity, Strings.json.complexityAverage].forEach(function(seriesName) { + if (!(seriesName in samples)) + return; + + var regression = {}; + result[seriesName] = regression; + var regressionResult = findRegression(samples[seriesName], predominantProfile); + if (seriesName == Strings.json.complexity) + complexitySamples = regressionResult.samples; + var calculation = regressionResult.regression; + regression[Strings.json.regressions.segment1] = [ + [regressionResult.minComplexity, calculation.s1 + calculation.t1 * regressionResult.minComplexity], + [calculation.complexity, calculation.s1 + calculation.t1 * calculation.complexity] + ]; + regression[Strings.json.regressions.segment2] = [ + [calculation.complexity, calculation.s2 + calculation.t2 * calculation.complexity], + [regressionResult.maxComplexity, calculation.s2 + calculation.t2 * regressionResult.maxComplexity] + ]; + regression[Strings.json.complexity] = calculation.complexity; + regression[Strings.json.measurements.stdev] = Math.sqrt(calculation.error / samples[seriesName].length); + }); + + if (isRampController) { + var timeComplexity = new Experiment; + data[Strings.json.controller].forEach(function(regression) { + timeComplexity.sample(regression[Strings.json.complexity]); + }); + + var experimentResult = {}; + result[Strings.json.controller] = experimentResult; + experimentResult[Strings.json.score] = timeComplexity.mean(); + experimentResult[Strings.json.measurements.average] = timeComplexity.mean(); + experimentResult[Strings.json.measurements.stdev] = timeComplexity.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = timeComplexity.percentage(); + + const bootstrapIterations = 2500; + var bootstrapResult = Regression.bootstrap(complexitySamples.data, bootstrapIterations, function(resampleData) { + var complexityIndex = complexitySamples.fieldMap[Strings.json.complexity]; + resampleData.sort(function(a, b) { + return a[complexityIndex] - b[complexityIndex]; + }); + + var resample = new SampleData(complexitySamples.fieldMap, resampleData); + var regressionResult = findRegression(resample, predominantProfile); + return regressionResult.regression.complexity; + }, .8); + + result[Strings.json.complexity][Strings.json.bootstrap] = bootstrapResult; + result[Strings.json.score] = bootstrapResult.median; + result[Strings.json.scoreLowerBound] = bootstrapResult.confidenceLow; + result[Strings.json.scoreUpperBound] = bootstrapResult.confidenceHigh; + } else { + var marks = data[Strings.json.marks]; + var samplingStartIndex = 0, samplingEndIndex = -1; + if (Strings.json.samplingStartTimeOffset in marks) + samplingStartIndex = marks[Strings.json.samplingStartTimeOffset].index; + if (Strings.json.samplingEndTimeOffset in marks) + samplingEndIndex = marks[Strings.json.samplingEndTimeOffset].index; + + var averageComplexity = new Experiment; + var averageFrameLength = new Experiment; + var controllerSamples = samples[Strings.json.controller]; + controllerSamples.forEach(function (sample, i) { + if (i >= samplingStartIndex && (samplingEndIndex == -1 || i < samplingEndIndex)) { + averageComplexity.sample(controllerSamples.getFieldInDatum(sample, Strings.json.complexity)); + var smoothedFrameLength = controllerSamples.getFieldInDatum(sample, Strings.json.smoothedFrameLength); + if (smoothedFrameLength && smoothedFrameLength != -1) + averageFrameLength.sample(smoothedFrameLength); + } + }); + + var experimentResult = {}; + result[Strings.json.controller] = experimentResult; + experimentResult[Strings.json.measurements.average] = averageComplexity.mean(); + experimentResult[Strings.json.measurements.concern] = averageComplexity.concern(Experiment.defaults.CONCERN); + experimentResult[Strings.json.measurements.stdev] = averageComplexity.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = averageComplexity.percentage(); + + experimentResult = {}; + result[Strings.json.frameLength] = experimentResult; + experimentResult[Strings.json.measurements.average] = 1000 / averageFrameLength.mean(); + experimentResult[Strings.json.measurements.concern] = averageFrameLength.concern(Experiment.defaults.CONCERN); + experimentResult[Strings.json.measurements.stdev] = averageFrameLength.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = averageFrameLength.percentage(); + + result[Strings.json.score] = averageComplexity.score(Experiment.defaults.CONCERN); + result[Strings.json.scoreLowerBound] = result[Strings.json.score] - averageFrameLength.standardDeviation(); + result[Strings.json.scoreUpperBound] = result[Strings.json.score] + averageFrameLength.standardDeviation(); + } + }, + + get data() + { + return this._iterationsSamplers; + }, + + get results() + { + if (this._results) + return this._results[Strings.json.results.iterations]; + this._processData(); + return this._results[Strings.json.results.iterations]; + }, + + get options() + { + return this._options; + }, + + _getResultsProperty: function(property) + { + if (this._results) + return this._results[property]; + this._processData(); + return this._results[property]; + }, + + get score() + { + return this._getResultsProperty(Strings.json.score); + }, + + get scoreLowerBound() + { + return this._getResultsProperty(Strings.json.scoreLowerBound); + }, + + get scoreUpperBound() + { + return this._getResultsProperty(Strings.json.scoreUpperBound); + } +}); + +ResultsTable = Utilities.createClass( + function(element, headers) + { + this.element = element; + this._headers = headers; + + this._flattenedHeaders = []; + this._headers.forEach(function(header) { + if (header.disabled) + return; + + if (header.children) + this._flattenedHeaders = this._flattenedHeaders.concat(header.children); + else + this._flattenedHeaders.push(header); + }, this); + + this._flattenedHeaders = this._flattenedHeaders.filter(function (header) { + return !header.disabled; + }); + + this.clear(); + }, { + + clear: function() + { + this.element.textContent = ""; + }, + + _addHeader: function() + { + var thead = Utilities.createElement("thead", {}, this.element); + var row = Utilities.createElement("tr", {}, thead); + + this._headers.forEach(function (header) { + if (header.disabled) + return; + + var th = Utilities.createElement("th", {}, row); + if (header.title != Strings.text.graph) + th.innerHTML = header.title; + if (header.children) + th.colSpan = header.children.length; + }); + }, + + _addBody: function() + { + this.tbody = Utilities.createElement("tbody", {}, this.element); + }, + + _addEmptyRow: function() + { + var row = Utilities.createElement("tr", {}, this.tbody); + this._flattenedHeaders.forEach(function (header) { + return Utilities.createElement("td", { class: "suites-separator" }, row); + }); + }, + + _addTest: function(testName, testResult, options) + { + var row = Utilities.createElement("tr", {}, this.tbody); + + this._flattenedHeaders.forEach(function (header) { + var td = Utilities.createElement("td", {}, row); + if (header.text == Strings.text.testName) { + td.textContent = testName; + } else if (typeof header.text == "string") { + var data = testResult[header.text]; + if (typeof data == "number") + data = data.toFixed(2); + td.innerHTML = data; + } else + td.innerHTML = header.text(testResult); + }, this); + }, + + _addIteration: function(iterationResult, iterationData, options) + { + var testsResults = iterationResult[Strings.json.results.tests]; + for (var suiteName in testsResults) { + this._addEmptyRow(); + var suiteResult = testsResults[suiteName]; + var suiteData = iterationData[suiteName]; + for (var testName in suiteResult) + this._addTest(testName, suiteResult[testName], options, suiteData[testName]); + } + }, + + showIterations: function(dashboard) + { + this.clear(); + this._addHeader(); + this._addBody(); + + var iterationsResults = dashboard.results; + iterationsResults.forEach(function(iterationResult, index) { + this._addIteration(iterationResult, dashboard.data[index], dashboard.options); + }, this); + } +}); + +window.benchmarkRunnerClient = { + iterationCount: 1, + options: null, + results: null, + + initialize: function(suites, options) + { + this.options = options; + }, + + willStartFirstIteration: function() + { + this.results = new ResultsDashboard(this.options); + }, + + didRunSuites: function(suitesSamplers) + { + this.results.push(suitesSamplers); + }, + + didRunTest: function(testData) + { + this.results.calculateScore(testData); + }, + + didFinishLastIteration: function() + { + benchmarkController.showResults(); + } +}; + +window.sectionsManager = +{ + showSection: function(sectionIdentifier, pushState) + { + var sections = document.querySelectorAll("main > section"); + for (var i = 0; i < sections.length; ++i) { + document.body.classList.remove("showing-" + sections[i].id); + } + document.body.classList.add("showing-" + sectionIdentifier); + + var currentSectionElement = document.querySelector("section.selected"); + console.assert(currentSectionElement); + + var newSectionElement = document.getElementById(sectionIdentifier); + console.assert(newSectionElement); + + currentSectionElement.classList.remove("selected"); + newSectionElement.classList.add("selected"); + + if (pushState) + history.pushState({section: sectionIdentifier}, document.title); + }, + + setSectionScore: function(sectionIdentifier, score, confidence) + { + document.querySelector("#" + sectionIdentifier + " .score").textContent = score; + if (confidence) + document.querySelector("#" + sectionIdentifier + " .confidence").textContent = confidence; + }, + + populateTable: function(tableIdentifier, headers, dashboard) + { + var table = new ResultsTable(document.getElementById(tableIdentifier), headers); + table.showIterations(dashboard); + } +}; + +window.benchmarkController = { + initialize: function() + { + benchmarkController.addOrientationListenerIfNecessary(); + }, + + determineCanvasSize: function() { + var match = window.matchMedia("(max-device-width: 760px)"); + if (match.matches) { + document.body.classList.add("small"); + return; + } + + match = window.matchMedia("(max-device-width: 1600px)"); + if (match.matches) { + document.body.classList.add("medium"); + return; + } + + match = window.matchMedia("(max-width: 1600px)"); + if (match.matches) { + document.body.classList.add("medium"); + return; + } + + document.body.classList.add("large"); + }, + + addOrientationListenerIfNecessary: function() { + if (!("orientation" in window)) + return; + + this.orientationQuery = window.matchMedia("(orientation: landscape)"); + this._orientationChanged(this.orientationQuery); + this.orientationQuery.addListener(this._orientationChanged); + }, + + _orientationChanged: function(match) + { + benchmarkController.isInLandscapeOrientation = match.matches; + if (match.matches) + document.querySelector(".start-benchmark p").classList.add("hidden"); + else + document.querySelector(".start-benchmark p").classList.remove("hidden"); + benchmarkController.updateStartButtonState(); + }, + + updateStartButtonState: function() + { + document.getElementById("run-benchmark").disabled = !this.isInLandscapeOrientation; + }, + + _startBenchmark: function(suites, options, frameContainerID) + { + benchmarkController.determineCanvasSize(); + + var configuration = document.body.className.match(/small|medium|large/); + if (configuration) + options[Strings.json.configuration] = configuration[0]; + + benchmarkRunnerClient.initialize(suites, options); + var frameContainer = document.getElementById(frameContainerID); + var runner = new BenchmarkRunner(suites, frameContainer, benchmarkRunnerClient); + runner.runMultipleIterations(); + + sectionsManager.showSection("test-container"); + }, + + startBenchmark: function() + { + var options = { + "test-interval": 30, + "display": "minimal", + "tiles": "big", + "controller": "ramp", + "kalman-process-error": 1, + "kalman-measurement-error": 4, + "time-measurement": "performance" + }; + this._startBenchmark(Suites, options, "test-container"); + }, + + showResults: function() + { + if (!this.addedKeyEvent) { + document.addEventListener("keypress", this.handleKeyPress, false); + this.addedKeyEvent = true; + } + + var dashboard = benchmarkRunnerClient.results; + var score = dashboard.score; + var confidence = "±" + (Statistics.largestDeviationPercentage(dashboard.scoreLowerBound, score, dashboard.scoreUpperBound) * 100).toFixed(2) + "%"; + sectionsManager.setSectionScore("results", score.toFixed(2), confidence); + sectionsManager.populateTable("results-header", Headers.testName, dashboard); + sectionsManager.populateTable("results-score", Headers.score, dashboard); + sectionsManager.populateTable("results-data", Headers.details, dashboard); + sectionsManager.showSection("results", true); + }, + + handleKeyPress: function(event) + { + switch (event.charCode) + { + case 27: // esc + benchmarkController.hideDebugInfo(); + break; + case 106: // j + benchmarkController.showDebugInfo(); + break; + case 115: // s + benchmarkController.selectResults(event.target); + break; + } + }, + + hideDebugInfo: function() + { + var overlay = document.getElementById("overlay"); + if (!overlay) + return; + document.body.removeChild(overlay); + }, + + showDebugInfo: function() + { + if (document.getElementById("overlay")) + return; + + var overlay = Utilities.createElement("div", { + id: "overlay" + }, document.body); + var container = Utilities.createElement("div", {}, overlay); + + var header = Utilities.createElement("h3", {}, container); + header.textContent = "Debug Output"; + + var data = Utilities.createElement("div", {}, container); + data.textContent = "Please wait..."; + setTimeout(function() { + var output = { + options: benchmarkRunnerClient.results.options, + data: benchmarkRunnerClient.results.data + }; + data.textContent = JSON.stringify(output, function(key, value) { + if (typeof value === 'number') + return Utilities.toFixedNumber(value, 3); + return value; + }, 1); + }, 0); + data.onclick = function() { + var selection = window.getSelection(); + selection.removeAllRanges(); + var range = document.createRange(); + range.selectNode(data); + selection.addRange(range); + }; + + var button = Utilities.createElement("button", {}, container); + button.textContent = "Done"; + button.onclick = function() { + benchmarkController.hideDebugInfo(); + }; + }, + + selectResults: function(target) + { + target.selectRange = ((target.selectRange || 0) + 1) % 3; + + var selection = window.getSelection(); + selection.removeAllRanges(); + var range = document.createRange(); + switch (target.selectRange) { + case 0: { + range.selectNode(document.getElementById("results-score")); + break; + } + case 1: { + range.setStart(document.querySelector("#results .score"), 0); + range.setEndAfter(document.querySelector("#results-score"), 0); + break; + } + case 2: { + range.selectNodeContents(document.querySelector("#results .score")); + break; + } + } + selection.addRange(range); + } +}; + +window.addEventListener("load", function() { benchmarkController.initialize(); }); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js new file mode 100644 index 0000000000..1aa630356c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js @@ -0,0 +1,179 @@ +BenchmarkRunnerState = Utilities.createClass( + function(suites) + { + this._suites = suites; + this._suiteIndex = -1; + this._testIndex = 0; + this.next(); + }, { + + currentSuite: function() + { + return this._suites[this._suiteIndex]; + }, + + currentTest: function() + { + var suite = this.currentSuite(); + return suite ? suite.tests[this._testIndex] : null; + }, + + isFirstTest: function() + { + return !this._testIndex; + }, + + next: function() + { + this._testIndex++; + + var suite = this._suites[this._suiteIndex]; + if (suite && this._testIndex < suite.tests.length) + return; + + this._testIndex = 0; + do { + this._suiteIndex++; + } while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled); + }, + + prepareCurrentTest: function(runner, frame) + { + var test = this.currentTest(); + var promise = new SimplePromise; + + frame.onload = function() { + promise.resolve(); + }; + + frame.src = "tests/" + test.url; + return promise; + } +}); + +BenchmarkRunner = Utilities.createClass( + function(suites, frameContainer, client) + { + this._suites = suites; + this._client = client; + this._frameContainer = frameContainer; + }, { + + _appendFrame: function() + { + var frame = document.createElement("iframe"); + frame.setAttribute("scrolling", "no"); + + this._frameContainer.insertBefore(frame, this._frameContainer.firstChild); + this._frame = frame; + return frame; + }, + + _removeFrame: function() + { + if (this._frame) { + this._frame.parentNode.removeChild(this._frame); + this._frame = null; + } + }, + + _runBenchmarkAndRecordResults: function(state) + { + var promise = new SimplePromise; + var suite = state.currentSuite(); + var test = state.currentTest(); + + if (this._client && this._client.willRunTest) + this._client.willRunTest(suite, test); + + var contentWindow = this._frame.contentWindow; + var self = this; + + var options = { complexity: test.complexity }; + Utilities.extendObject(options, this._client.options); + Utilities.extendObject(options, contentWindow.Utilities.parseParameters()); + + var benchmark = new contentWindow.benchmarkClass(options); + document.body.style.backgroundColor = benchmark.backgroundColor(); + benchmark.run().then(function(testData) { + var suiteResults = self._suitesResults[suite.name] || {}; + suiteResults[test.name] = testData; + self._suitesResults[suite.name] = suiteResults; + + if (self._client && self._client.didRunTest) + self._client.didRunTest(testData); + + state.next(); + if (state.currentSuite() != suite) + self._removeFrame(); + promise.resolve(state); + }); + + return promise; + }, + + step: function(state) + { + if (!state) { + state = new BenchmarkRunnerState(this._suites); + this._suitesResults = {}; + } + + var suite = state.currentSuite(); + if (!suite) { + this._finalize(); + var promise = new SimplePromise; + promise.resolve(); + return promise; + } + + if (state.isFirstTest()) { + this._appendFrame(); + } + + return state.prepareCurrentTest(this, this._frame).then(function(prepareReturnValue) { + return this._runBenchmarkAndRecordResults(state); + }.bind(this)); + }, + + runAllSteps: function(startingState) + { + var nextCallee = this.runAllSteps.bind(this); + this.step(startingState).then(function(nextState) { + if (nextState) + nextCallee(nextState); + }); + }, + + runMultipleIterations: function() + { + var self = this; + var currentIteration = 0; + + this._runNextIteration = function() { + currentIteration++; + if (currentIteration < self._client.iterationCount) + self.runAllSteps(); + else if (this._client && this._client.didFinishLastIteration) { + document.body.style.backgroundColor = ""; + self._client.didFinishLastIteration(); + } + } + + if (this._client && this._client.willStartFirstIteration) + this._client.willStartFirstIteration(); + + this.runAllSteps(); + }, + + _finalize: function() + { + this._removeFrame(); + + if (this._client && this._client.didRunSuites) + this._client.didRunSuites(this._suitesResults); + + if (this._runNextIteration) + this._runNextIteration(); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg new file mode 100644 index 0000000000..0090df6c0c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg new file mode 100644 index 0000000000..83458b8095 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg new file mode 100644 index 0000000000..a7d0eaf375 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js new file mode 100644 index 0000000000..aa938c5189 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js @@ -0,0 +1,81 @@ +var Headers = { + testName: [ + { + title: "" + Strings.text.testName + "", + text: Strings.text.testName + } + ], + score: [ + { + title: Strings.text.score, + text: Strings.json.score + } + ], + details: [ + { + title: " ", + text: function(data) { + var bootstrap = data[Strings.json.complexity][Strings.json.bootstrap]; + return "±" + (Statistics.largestDeviationPercentage(bootstrap.confidenceLow, bootstrap.median, bootstrap.confidenceHigh) * 100).toFixed(2) + "%"; + } + } + ] +}; + +var Suite = function(name, tests) { + this.name = name; + this.tests = tests; +}; + +var Suites = []; + +Suites.push(new Suite("Animometer", + [ + { + url: "master/multiply.html", + name: "Multiply" + }, + { + url: "master/canvas-stage.html?pathType=arcs", + name: "Canvas Arcs" + }, + { + url: "master/leaves.html", + name: "Leaves" + }, + { + url: "master/canvas-stage.html?pathType=linePath", + name: "Paths" + }, + { + url: "master/canvas-stage.html?pathType=line&lineCap=square", + name: "Canvas Lines" + }, + { + url: "master/focus.html", + name: "Focus" + }, + { + url: "master/image-data.html", + name: "Images" + }, + { + url: "master/text.html", + name: "Design" + }, + { + url: "master/svg-particles.html", + name: "Suits" + }, + ] +)); + +function suiteFromName(name) +{ + return Suites.find(function(suite) { return suite.name == name; }); +} + +function testFromName(suite, name) +{ + return suite.tests.find(function(test) { return test.name == name; }); +} diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/statistics.js b/third_party/webkit/PerformanceTests/MotionMark/resources/statistics.js new file mode 100644 index 0000000000..9322a797b6 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/statistics.js @@ -0,0 +1,397 @@ +Pseudo = +{ + initialRandomSeed: 49734321, + randomSeed: 49734321, + + resetRandomSeed: function() + { + Pseudo.randomSeed = Pseudo.initialRandomSeed; + }, + + random: function() + { + var randomSeed = Pseudo.randomSeed; + randomSeed = ((randomSeed + 0x7ed55d16) + (randomSeed << 12)) & 0xffffffff; + randomSeed = ((randomSeed ^ 0xc761c23c) ^ (randomSeed >>> 19)) & 0xffffffff; + randomSeed = ((randomSeed + 0x165667b1) + (randomSeed << 5)) & 0xffffffff; + randomSeed = ((randomSeed + 0xd3a2646c) ^ (randomSeed << 9)) & 0xffffffff; + randomSeed = ((randomSeed + 0xfd7046c5) + (randomSeed << 3)) & 0xffffffff; + randomSeed = ((randomSeed ^ 0xb55a4f09) ^ (randomSeed >>> 16)) & 0xffffffff; + Pseudo.randomSeed = randomSeed; + return (randomSeed & 0xfffffff) / 0x10000000; + } +}; + +Statistics = +{ + sampleMean: function(numberOfSamples, sum) + { + if (numberOfSamples < 1) + return 0; + return sum / numberOfSamples; + }, + + // With sum and sum of squares, we can compute the sample standard deviation in O(1). + // See https://rniwa.com/2012-11-10/sample-standard-deviation-in-terms-of-sum-and-square-sum-of-samples/ + unbiasedSampleStandardDeviation: function(numberOfSamples, sum, squareSum) + { + if (numberOfSamples < 2) + return 0; + return Math.sqrt((squareSum - sum * sum / numberOfSamples) / (numberOfSamples - 1)); + }, + + geometricMean: function(values) + { + if (!values.length) + return 0; + var roots = values.map(function(value) { return Math.pow(value, 1 / values.length); }) + return roots.reduce(function(a, b) { return a * b; }); + }, + + // Cumulative distribution function + cdf: function(value, mean, standardDeviation) + { + return 0.5 * (1 + Statistics.erf((value - mean) / (Math.sqrt(2 * standardDeviation * standardDeviation)))); + }, + + // Approximation of Gauss error function, Abramowitz and Stegun 7.1.26 + erf: function(value) + { + var sign = (value >= 0) ? 1 : -1; + value = Math.abs(value); + + var a1 = 0.254829592; + var a2 = -0.284496736; + var a3 = 1.421413741; + var a4 = -1.453152027; + var a5 = 1.061405429; + var p = 0.3275911; + + var t = 1.0 / (1.0 + p * value); + var y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-value * value); + return sign * y; + }, + + largestDeviationPercentage: function(low, mean, high) + { + return Math.max(Math.abs(low / mean - 1), (high / mean - 1)); + } +}; + +Experiment = Utilities.createClass( + function(includeConcern) + { + if (includeConcern) + this._maxHeap = Heap.createMaxHeap(Experiment.defaults.CONCERN_SIZE); + this.reset(); + }, { + + reset: function() + { + this._sum = 0; + this._squareSum = 0; + this._numberOfSamples = 0; + if (this._maxHeap) + this._maxHeap.init(); + }, + + get sampleCount() + { + return this._numberOfSamples; + }, + + sample: function(value) + { + this._sum += value; + this._squareSum += value * value; + if (this._maxHeap) + this._maxHeap.push(value); + ++this._numberOfSamples; + }, + + mean: function() + { + return Statistics.sampleMean(this._numberOfSamples, this._sum); + }, + + standardDeviation: function() + { + return Statistics.unbiasedSampleStandardDeviation(this._numberOfSamples, this._sum, this._squareSum); + }, + + cdf: function(value) + { + return Statistics.cdf(value, this.mean(), this.standardDeviation()); + }, + + percentage: function() + { + var mean = this.mean(); + return mean ? this.standardDeviation() * 100 / mean : 0; + }, + + concern: function(percentage) + { + if (!this._maxHeap) + return this.mean(); + + var size = Math.ceil(this._numberOfSamples * percentage / 100); + var values = this._maxHeap.values(size); + return values.length ? values.reduce(function(a, b) { return a + b; }) / values.length : 0; + }, + + score: function(percentage) + { + return Statistics.geometricMean([this.mean(), Math.max(this.concern(percentage), 1)]); + } +}); + +Experiment.defaults = +{ + CONCERN: 5, + CONCERN_SIZE: 100, +}; + +Regression = Utilities.createClass( + function(samples, getComplexity, getFrameLength, startIndex, endIndex, options) + { + var desiredFrameLength = options.desiredFrameLength || 1000/60; + var bestProfile; + + if (!options.preferredProfile || options.preferredProfile == Strings.json.profiles.slope) { + var slope = this._calculateRegression(samples, getComplexity, getFrameLength, startIndex, endIndex, { + shouldClip: true, + s1: desiredFrameLength, + t1: 0 + }); + if (!bestProfile || slope.error < bestProfile.error) { + bestProfile = slope; + this.profile = Strings.json.profiles.slope; + } + } + if (!options.preferredProfile || options.preferredProfile == Strings.json.profiles.flat) { + var flat = this._calculateRegression(samples, getComplexity, getFrameLength, startIndex, endIndex, { + shouldClip: true, + s1: desiredFrameLength, + t1: 0, + t2: 0 + }); + + if (!bestProfile || flat.error < bestProfile.error) { + bestProfile = flat; + this.profile = Strings.json.profiles.flat; + } + } + + this.startIndex = Math.min(startIndex, endIndex); + this.endIndex = Math.max(startIndex, endIndex); + + this.complexity = bestProfile.complexity; + this.s1 = bestProfile.s1; + this.t1 = bestProfile.t1; + this.s2 = bestProfile.s2; + this.t2 = bestProfile.t2; + this.stdev1 = bestProfile.stdev1; + this.stdev2 = bestProfile.stdev2; + this.n1 = bestProfile.n1; + this.n2 = bestProfile.n2; + this.error = bestProfile.error; + }, { + + valueAt: function(complexity) + { + if (this.n1 == 1 || complexity > this.complexity) + return this.s2 + this.t2 * complexity; + return this.s1 + this.t1 * complexity; + }, + + // A generic two-segment piecewise regression calculator. Based on Kundu/Ubhaya + // + // Minimize sum of (y - y')^2 + // where y = s1 + t1*x + // y = s2 + t2*x + // y' = s1 + t1*x' = s2 + t2*x' if x_0 <= x' <= x_n + // + // Allows for fixing s1, t1, s2, t2 + // + // x is assumed to be complexity, y is frame length. Can be used for pure complexity-FPS + // analysis or for ramp controllers since complexity monotonically decreases with time. + _calculateRegression: function(samples, getComplexity, getFrameLength, startIndex, endIndex, options) + { + if (startIndex == endIndex) { + // Only one sample point; we can't calculate any regression. + var x = getComplexity(samples, startIndex); + return { + complexity: x, + s1: x, + t1: 0, + s2: x, + t2: 0, + error1: 0, + error2: 0 + }; + } + + // x is expected to increase in complexity + var iterationDirection = endIndex > startIndex ? 1 : -1; + var lowComplexity = getComplexity(samples, startIndex); + var highComplexity = getComplexity(samples, endIndex); + var a1 = 0, b1 = 0, c1 = 0, d1 = 0, h1 = 0, k1 = 0; + var a2 = 0, b2 = 0, c2 = 0, d2 = 0, h2 = 0, k2 = 0; + + // Iterate from low to high complexity + for (var i = startIndex; iterationDirection * (endIndex - i) > -1; i += iterationDirection) { + var x = getComplexity(samples, i); + var y = getFrameLength(samples, i); + a2 += 1; + b2 += x; + c2 += x * x; + d2 += y; + h2 += y * x; + k2 += y * y; + } + + var s1_best, t1_best, s2_best, t2_best, n1_best, n2_best, error1_best, error2_best, x_best, x_prime; + + function setBest(s1, t1, error1, s2, t2, error2, splitIndex, x_prime, x) + { + s1_best = s1; + t1_best = t1; + error1_best = error1; + s2_best = s2; + t2_best = t2; + error2_best = error2; + // Number of samples included in the first segment, inclusive of splitIndex + n1_best = iterationDirection * (splitIndex - startIndex) + 1; + // Number of samples included in the second segment + n2_best = iterationDirection * (endIndex - splitIndex); + if (!options.shouldClip || (x_prime >= lowComplexity && x_prime <= highComplexity)) + x_best = x_prime; + else { + // Discontinuous piecewise regression + x_best = x; + } + } + + // Iterate from startIndex to endIndex - 1, inclusive + for (var i = startIndex; iterationDirection * (endIndex - i) > 0; i += iterationDirection) { + var x = getComplexity(samples, i); + var y = getFrameLength(samples, i); + var xx = x * x; + var yx = y * x; + var yy = y * y; + // a1, b1, etc. is sum from startIndex to i, inclusive + a1 += 1; + b1 += x; + c1 += xx; + d1 += y; + h1 += yx; + k1 += yy; + // a2, b2, etc. is sum from i+1 to endIndex, inclusive + a2 -= 1; + b2 -= x; + c2 -= xx; + d2 -= y; + h2 -= yx; + k2 -= yy; + + var A = c1*d1 - b1*h1; + var B = a1*h1 - b1*d1; + var C = a1*c1 - b1*b1; + var D = c2*d2 - b2*h2; + var E = a2*h2 - b2*d2; + var F = a2*c2 - b2*b2; + var s1 = options.s1 !== undefined ? options.s1 : (A / C); + var t1 = options.t1 !== undefined ? options.t1 : (B / C); + var s2 = options.s2 !== undefined ? options.s2 : (D / F); + var t2 = options.t2 !== undefined ? options.t2 : (E / F); + // Assumes that the two segments meet + var x_prime = (s1 - s2) / (t2 - t1); + + var error1 = (k1 + a1*s1*s1 + c1*t1*t1 - 2*d1*s1 - 2*h1*t1 + 2*b1*s1*t1) || Number.MAX_VALUE; + var error2 = (k2 + a2*s2*s2 + c2*t2*t2 - 2*d2*s2 - 2*h2*t2 + 2*b2*s2*t2) || Number.MAX_VALUE; + + if (i == startIndex) { + setBest(s1, t1, error1, s2, t2, error2, i, x_prime, x); + continue; + } + + if (C == 0 || F == 0) + continue; + + // Projected point is not between this and the next sample + if (x_prime > getComplexity(samples, i + iterationDirection) || x_prime < x) { + // Calculate lambda, which divides the weight of this sample between the two lines + + // These values remove the influence of this sample + var I = c1 - 2*b1*x + a1*xx; + var H = C - I; + var G = A + B*x - C*y; + + var J = D + E*x - F*y; + var K = c2 - 2*b2*x + a2*xx; + + var lambda = (G*F + G*K - H*J) / (I*J + G*K); + if (lambda > 0 && lambda < 1) { + var lambda1 = 1 - lambda; + s1 = options.s1 !== undefined ? options.s1 : ((A - lambda1*(-h1*x + d1*xx + c1*y - b1*yx)) / (C - lambda1*I)); + t1 = options.t1 !== undefined ? options.t1 : ((B - lambda1*(h1 - d1*x - b1*y + a1*yx)) / (C - lambda1*I)); + s2 = options.s2 !== undefined ? options.s2 : ((D + lambda1*(-h2*x + d2*xx + c2*y - b2*yx)) / (F + lambda1*K)); + t2 = options.t2 !== undefined ? options.t2 : ((E + lambda1*(h2 - d2*x - b2*y + a2*yx)) / (F + lambda1*K)); + x_prime = (s1 - s2) / (t2 - t1); + + error1 = ((k1 + a1*s1*s1 + c1*t1*t1 - 2*d1*s1 - 2*h1*t1 + 2*b1*s1*t1) - lambda1 * Math.pow(y - (s1 + t1*x), 2)) || Number.MAX_VALUE; + error2 = ((k2 + a2*s2*s2 + c2*t2*t2 - 2*d2*s2 - 2*h2*t2 + 2*b2*s2*t2) + lambda1 * Math.pow(y - (s2 + t2*x), 2)) || Number.MAX_VALUE; + } else if (t1 != t2) + continue; + } + + if (error1 + error2 < error1_best + error2_best) + setBest(s1, t1, error1, s2, t2, error2, i, x_prime, x); + } + + return { + complexity: x_best, + s1: s1_best, + t1: t1_best, + stdev1: Math.sqrt(error1_best / n1_best), + s2: s2_best, + t2: t2_best, + stdev2: Math.sqrt(error2_best / n2_best), + error: error1_best + error2_best, + n1: n1_best, + n2: n2_best + }; + } +}); + +Utilities.extendObject(Regression, { + bootstrap: function(samples, iterationCount, processResample, confidencePercentage) + { + var sampleLength = samples.length; + var resample = new Array(sampleLength); + + var bootstrapEstimator = new Experiment; + var bootstrapData = new Array(iterationCount); + + Pseudo.resetRandomSeed(); + for (var i = 0; i < iterationCount; ++i) { + for (var j = 0; j < sampleLength; ++j) + resample[j] = samples[Math.floor(Pseudo.random() * sampleLength)]; + + var resampleResult = processResample(resample); + bootstrapEstimator.sample(resampleResult); + bootstrapData[i] = resampleResult; + } + + bootstrapData.sort(function(a, b) { return a - b; }); + return { + confidenceLow: bootstrapData[Math.round((iterationCount - 1) * (1 - confidencePercentage) / 2)], + confidenceHigh: bootstrapData[Math.round((iterationCount - 1) * (1 + confidencePercentage) / 2)], + median: bootstrapData[Math.round(iterationCount / 2)], + mean: bootstrapEstimator.mean(), + data: bootstrapData, + confidencePercentage: confidencePercentage + }; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/strings.js b/third_party/webkit/PerformanceTests/MotionMark/resources/strings.js new file mode 100644 index 0000000000..b58f67e991 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/strings.js @@ -0,0 +1,51 @@ +var Strings = { + text: { + testName: "Test Name", + score: "Score" + }, + json: { + marks: "marks", + samplingStartTimeOffset: "Start sampling", + samplingEndTimeOffset: "End sampling", + + samples: "samples", + dataFieldMap: "dataFieldMap", + controller: "controller", + time: "time", + complexity: "complexity", + complexityAverage: "complexityAverage", + frameLength: "frameLength", + smoothedFrameLength: "smoothedFrameLength", + + result: "result", + configuration: "configuration", + score: "score", + scoreLowerBound: "scoreLowerBound", + scoreUpperBound: "scoreUpperBound", + bootstrap: "bootstrap", + measurements: { + average: "average", + concern: "concern", + stdev: "stdev", + percent: "percent" + }, + + regressions: { + startIndex: "startIndex", + endIndex: "endIndex", + segment1: "segment1", + segment2: "segment2", + profile: "profile" + }, + + profiles: { + slope: "slope", + flat: "flat" + }, + + results: { + iterations: "iterationsResults", + tests: "testsResults" + } + } +}; diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js new file mode 100644 index 0000000000..58f5df385e --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js @@ -0,0 +1,184 @@ +(function() { + +WebGLStage = Utilities.createSubclass(Stage, + function(element, options) + { + Stage.call(this); + }, + { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + + this._numTriangles = 0; + this._bufferSize = 0; + + this._gl = this.element.getContext("webgl"); + var gl = this._gl; + + gl.clearColor(0.5, 0.5, 0.5, 1); + + // Create the vertex shader object. + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + + // The source code for the shader is extracted from the + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html new file mode 100644 index 0000000000..864c19adcd --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html new file mode 100644 index 0000000000..c759d45c08 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html new file mode 100644 index 0000000000..058de486de --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html @@ -0,0 +1,22 @@ + + + + + + + + +
    + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html new file mode 100644 index 0000000000..0c1248f490 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html @@ -0,0 +1,33 @@ + + + + + + + + +
    + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html new file mode 100644 index 0000000000..2b6a0b9db5 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html new file mode 100644 index 0000000000..a821231672 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html new file mode 100644 index 0000000000..f67f14ad36 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + +
    + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js new file mode 100644 index 0000000000..5fba5ad761 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js @@ -0,0 +1,47 @@ +(function() { + +BouncingCanvasImage = Utilities.createSubclass(BouncingCanvasParticle, + function(stage) + { + BouncingCanvasParticle.call(this, stage, "image"); + this._imageElement = stage.imageElement; + }, { + + _draw: function() + { + this.context.save(); + this.applyRotation(); + this.context.drawImage(this._imageElement, 0, 0, this.size.x, this.size.y); + this.context.restore(); + } +}); + +BouncingCanvasImagesStage = Utilities.createSubclass(BouncingCanvasParticlesStage, + function() + { + BouncingCanvasParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options); + var imageSrc = options["imageSrc"] || "resources/yin-yang.svg"; + this.imageElement = document.querySelector(".hidden[src=\"" + imageSrc + "\"]"); + }, + + createParticle: function() + { + return new BouncingCanvasImage(this); + } +}); + +BouncingCanvasImagesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingCanvasImagesStage(), options); + } +); + +window.benchmarkClass = BouncingCanvasImagesBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js new file mode 100644 index 0000000000..0a76ba05c3 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js @@ -0,0 +1,88 @@ +BouncingCanvasParticle = Utilities.createSubclass(BouncingParticle, + function(stage, shape) + { + BouncingParticle.call(this, stage); + this.context = stage.context; + this._shape = shape; + this._clip = stage.clip; + }, { + + applyRotation: function() + { + if (this._shape == "circle") + return; + + this.context.translate(this.size.x / 2, this.size.y / 2); + this.context.rotate(this.rotater.degree() * Math.PI / 180); + this.context.translate(-this.size.x / 2, -this.size.y / 2); + }, + + applyClipping: function() + { + var clipPoints = BouncingCanvasParticle.clips[this._clip]; + if (!clipPoints) + return; + + this.context.beginPath(); + clipPoints.forEach(function(point, index) { + var point = this.size.multiply(point); + if (!index) + this.context.moveTo(point.x, point.y); + else + this.context.lineTo(point.x, point.y); + }, this); + + this.context.closePath(); + this.context.clip(); + }, + + _draw: function() + { + throw "Not implemented"; + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this.context.save(); + this.context.translate(this.position.x, this.position.y); + this._draw(); + this.context.restore(); + } +}); + +BouncingCanvasParticle.clips = { + star: [ + new Point(0.50, 0.00), + new Point(0.38, 0.38), + new Point(0.00, 0.38), + new Point(0.30, 0.60), + new Point(0.18, 1.00), + new Point(0.50, 0.75), + new Point(0.82, 1.00), + new Point(0.70, 0.60), + new Point(1.00, 0.38), + new Point(0.62, 0.38) + ] +}; + +BouncingCanvasParticlesStage = Utilities.createSubclass(BouncingParticlesStage, + function() + { + BouncingParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); + this.context = this.element.getContext("2d"); + }, + + animate: function(timeDelta) + { + this.context.clearRect(0, 0, this.size.x, this.size.y); + this.particles.forEach(function(particle) { + particle.animate(timeDelta); + }); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js new file mode 100644 index 0000000000..49a31cf40d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js @@ -0,0 +1,87 @@ +(function() { + +BouncingCanvasShape = Utilities.createSubclass(BouncingCanvasParticle, + function(stage) + { + BouncingCanvasParticle.call(this, stage, stage.shape); + this._fill = stage.fill; + this._color0 = Stage.randomColor(); + this._color1 = Stage.randomColor(); + }, { + + _applyFill: function() + { + switch (this._fill) { + case "gradient": + var gradient = this.context.createLinearGradient(0, 0, this.size.width, 0); + gradient.addColorStop(0, this._color0); + gradient.addColorStop(1, this._color1); + this.context.fillStyle = gradient; + break; + + case "solid": + default: + this.context.fillStyle = this._color0; + break; + } + }, + + _drawShape: function() + { + this.context.beginPath(); + + switch (this._shape) { + case "rect": + this.context.rect(0, 0, this.size.width, this.size.height); + break; + + case "circle": + default: + var center = this.size.center; + var radius = Math.min(this.size.x, this.size.y) / 2; + this.context.arc(center.x, center.y, radius, 0, Math.PI * 2, true); + break; + } + + this.context.fill(); + }, + + _draw: function() + { + this.context.save(); + this._applyFill(); + this.applyRotation(); + this.applyClipping(); + this._drawShape(); + this.context.restore(); + } +}); + +BouncingCanvasShapesStage = Utilities.createSubclass(BouncingCanvasParticlesStage, + function () + { + BouncingCanvasParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options); + this.parseShapeParameters(options); + }, + + createParticle: function() + { + return new BouncingCanvasShape(this); + } +}); + +BouncingCanvasShapesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingCanvasShapesStage(), options); + } +); + +window.benchmarkClass = BouncingCanvasShapesBenchmark; + +})(); \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js new file mode 100644 index 0000000000..ce9a48c276 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js @@ -0,0 +1,61 @@ +(function() { + +BouncingCssImage = Utilities.createSubclass(BouncingParticle, + function(stage) + { + BouncingParticle.call(this, stage); + + this.element = document.createElement("img"); + this.element.style.width = this.size.x + "px"; + this.element.style.height = this.size.y + "px"; + this.element.setAttribute("src", stage.imageSrc); + + stage.element.appendChild(this.element); + this._move(); + }, { + + _move: function() + { + this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ(); + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this._move(); + } +}); + +BouncingCssImagesStage = Utilities.createSubclass(BouncingParticlesStage, + function() + { + BouncingParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); + this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg"; + }, + + createParticle: function() + { + return new BouncingCssImage(this); + }, + + particleWillBeRemoved: function(particle) + { + particle.element.remove(); + } +}); + +BouncingCssImagesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingCssImagesStage(), options); + } +); + +window.benchmarkClass = BouncingCssImagesBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js new file mode 100644 index 0000000000..a1f81863f9 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js @@ -0,0 +1,86 @@ +(function() { + +BouncingCssShape = Utilities.createSubclass(BouncingParticle, + function(stage) + { + BouncingParticle.call(this, stage); + + this.element = this._createSpan(stage); + + switch (stage.fill) { + case "solid": + default: + this.element.style.backgroundColor = Stage.randomColor(); + break; + + case "gradient": + this.element.style.background = "linear-gradient(" + Stage.randomColor() + ", " + Stage.randomColor() + ")"; + break; + } + + if (stage.blend) + this.element.style.mixBlendMode = Stage.randomStyleMixBlendMode(); + + // Some browsers have not un-prefixed the css filter yet. + if (stage.filter) + Utilities.setElementPrefixedProperty(this.element, "filter", Stage.randomStyleFilter()); + + this._move(); + }, { + + _createSpan: function(stage) + { + var span = document.createElement("span"); + span.className = stage.shape + " " + stage.clip; + span.style.width = this.size.x + "px"; + span.style.height = this.size.y + "px"; + stage.element.appendChild(span); + return span; + }, + + _move: function() + { + this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px)" + this.rotater.rotateZ(); + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this.rotater.next(timeDelta); + this._move(); + } +}); + +BouncingCssShapesStage = Utilities.createSubclass(BouncingParticlesStage, + function() + { + BouncingParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); + this.parseShapeParameters(options); + }, + + createParticle: function() + { + return new BouncingCssShape(this); + }, + + particleWillBeRemoved: function(particle) + { + particle.element.remove(); + } +}); + +BouncingCssShapesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingCssShapesStage(), options); + } +); + +window.benchmarkClass = BouncingCssShapesBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js new file mode 100644 index 0000000000..27e02a7085 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js @@ -0,0 +1,123 @@ +function BouncingParticle(stage) +{ + this._stageSize = stage.size; + this.size = stage.particleSize; + + this.position = Stage.randomPosition(stage.size.subtract(stage.particleSize)); + this._angle = Stage.randomAngle(); + this._velocity = Stage.randomVelocity(stage.maxVelocity); + this.rotater = Stage.randomRotater(); +} + +BouncingParticle.prototype = +{ + get center() + { + return this.position.add(this.size.center); + }, + + animate: function(timeDelta) + { + this.position = this.position.move(this._angle, this._velocity, timeDelta); + this.rotater.next(timeDelta); + + // If particle is going to move off right side + if (this.position.x + this.size.x > this._stageSize.x) { + // If direction is East-South, go West-South. + if (this._angle >= 0 && this._angle < Math.PI / 2) + this._angle = Math.PI - this._angle; + // If angle is East-North, go West-North. + else if (this._angle > Math.PI / 2 * 3) + this._angle = this._angle - (this._angle - Math.PI / 2 * 3) * 2; + // Make sure the particle does not go outside the stage boundaries. + this.position.x = this._stageSize.x - this.size.x; + } + + // If particle is going to move off left side + if (this.position.x < 0) { + // If angle is West-South, go East-South. + if (this._angle > Math.PI / 2 && this._angle < Math.PI) + this._angle = Math.PI - this._angle; + // If angle is West-North, go East-North. + else if (this._angle > Math.PI && this._angle < Math.PI / 2 * 3) + this._angle = this._angle + (Math.PI / 2 * 3 - this._angle) * 2; + // Make sure the particle does not go outside the stage boundaries. + this.position.x = 0; + } + + // If particle is going to move off bottom side + if (this.position.y + this.size.y > this._stageSize.y) { + // If direction is South, go North. + if (this._angle > 0 && this._angle < Math.PI) + this._angle = Math.PI * 2 - this._angle; + // Make sure the particle does not go outside the stage boundaries. + this.position.y = this._stageSize.y - this.size.y; + } + + // If particle is going to move off top side + if (this.position.y < 0) { + // If direction is North, go South. + if (this._angle > Math.PI && this._angle < Math.PI * 2) + this._angle = this._angle - (this._angle - Math.PI) * 2; + // Make sure the particle does not go outside the stage boundaries. + this.position.y = 0; + } + } +} + +BouncingParticlesStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + this.particles = []; + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + this.particleSize = new Point(parseInt(options["particleWidth"]) || 10, parseInt(options["particleHeight"]) || 10); + this.maxVelocity = Math.max(parseInt(options["maxVelocity"]) || 500, 100); + }, + + parseShapeParameters: function(options) + { + this.shape = options["shape"] || "circle"; + this.fill = options["fill"] || "solid"; + this.clip = options["clip"] || ""; + this.blend = options["blend"] || false; + this.filter = options["filter"] || false; + }, + + animate: function(timeDelta) + { + this.particles.forEach(function(particle) { + particle.animate(timeDelta); + }); + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count > 0) { + for (var i = 0; i < count; ++i) + this.particles.push(this.createParticle()); + return; + } + + count = Math.min(-count, this.particles.length); + + if (typeof(this.particleWillBeRemoved) == "function") { + for (var i = 0; i < count; ++i) + this.particleWillBeRemoved(this.particles[this.particles.length - 1 - i]); + } + + this.particles.splice(-count, count); + }, + + complexity: function() + { + return this.particles.length; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js new file mode 100644 index 0000000000..2239557312 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js @@ -0,0 +1,43 @@ +(function() { + +BouncingSvgImage = Utilities.createSubclass(BouncingSvgParticle, + function(stage) + { + BouncingSvgParticle.call(this, stage, "image"); + + var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y }; + var xlinkAttrs = { href: stage.imageSrc }; + this.element = Utilities.createSVGElement("image", attrs, xlinkAttrs, stage.element); + this._move(); + } +); + +BouncingSvgImagesStage = Utilities.createSubclass(BouncingSvgParticlesStage, + function() + { + BouncingSvgParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark, options); + this.imageSrc = options["imageSrc"] || "resources/yin-yang.svg"; + }, + + createParticle: function() + { + return new BouncingSvgImage(this); + } +}); + +BouncingSvgImagesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingSvgImagesStage(), options); + } +); + +window.benchmarkClass = BouncingSvgImagesBenchmark; + +})(); + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js new file mode 100644 index 0000000000..0988c42d8e --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js @@ -0,0 +1,67 @@ +BouncingSvgParticle = Utilities.createSubclass(BouncingParticle, + function(stage, shape) + { + BouncingParticle.call(this, stage); + this._shape = shape; + }, { + + _applyClipping: function(stage) + { + if (stage.clip != "star") + return; + + stage.ensureClipStarIsCreated(); + this.element.setAttribute("clip-path", "url(#star-clip)"); + }, + + _move: function() + { + var transform = "translate(" + this.position.x + ", " + this.position.y + ")"; + if (this._shape != "circle") + transform += this.rotater.rotate(this.size.center); + this.element.setAttribute("transform", transform); + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this._move(); + } +}); + +BouncingSvgParticlesStage = Utilities.createSubclass(BouncingParticlesStage, + function() + { + BouncingParticlesStage.call(this); + }, { + + _createDefs: function() + { + return Utilities.createSVGElement("defs", {}, {}, this.element); + }, + + _ensureDefsIsCreated: function() + { + return this.element.querySelector("defs") || this._createDefs(); + }, + + _createClipStar: function() + { + var attrs = { id: "star-clip", clipPathUnits: "objectBoundingBox" }; + var clipPath = Utilities.createSVGElement("clipPath", attrs, {}, this._ensureDefsIsCreated()); + + attrs = { d: "M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" }; + Utilities.createSVGElement("path", attrs, {}, clipPath); + return clipPath; + }, + + ensureClipStarIsCreated: function() + { + return this.element.querySelector("#star-clip") || this._createClipStar(); + }, + + particleWillBeRemoved: function(particle) + { + particle.element.remove(); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js new file mode 100644 index 0000000000..14c917cc31 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js @@ -0,0 +1,101 @@ +(function() { + +BouncingSvgShape = Utilities.createSubclass(BouncingSvgParticle, + function(stage) + { + BouncingSvgParticle.call(this, stage, stage.shape); + this._fill = stage.fill; + + this._createShape(stage); + this._applyClipping(stage); + this._applyFill(stage); + + this._move(); + }, { + + _createShape: function(stage) + { + switch (this._shape) { + case "rect": + var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y }; + this.element = Utilities.createSVGElement("rect", attrs, {}, stage.element); + break; + + case "circle": + default: + var attrs = { cx: this.size.x / 2, cy: this.size.y / 2, r: Math.min(this.size.x, this.size.y) / 2 }; + this.element = Utilities.createSVGElement("circle", attrs, {}, stage.element); + break; + } + }, + + _applyFill: function(stage) + { + switch (this._fill) { + case "gradient": + var gradient = stage.createGradient(2); + this.element.setAttribute("fill", "url(#" + gradient.getAttribute("id") + ")"); + break; + + case "solid": + default: + this.element.setAttribute("fill", Stage.randomColor()); + break; + } + } +}); + +BouncingSvgShapesStage = Utilities.createSubclass(BouncingSvgParticlesStage, + function() + { + BouncingSvgParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark, options); + this.parseShapeParameters(options); + this._gradientsCount = 0; + }, + + createGradient: function(stops) + { + var attrs = { id: "gradient-" + ++this._gradientsCount }; + var gradient = Utilities.createSVGElement("linearGradient", attrs, {}, this._ensureDefsIsCreated()); + + for (var i = 0; i < stops; ++i) { + attrs = { offset: i * 100 / (stops - 1) + "%", 'stop-color': Stage.randomColor() }; + Utilities.createSVGElement("stop", attrs, {}, gradient); + } + + return gradient; + }, + + createParticle: function() + { + return new BouncingSvgShape(this); + }, + + particleWillBeRemoved: function(particle) + { + BouncingSvgParticlesStage.prototype.particleWillBeRemoved.call(this, particle); + + var fill = particle.element.getAttribute("fill"); + if (fill.indexOf("url(#") != 0) + return; + + var gradient = this.element.querySelector(fill.substring(4, fill.length - 1)); + this._ensureDefsIsCreated().removeChild(gradient); + } +}); + +BouncingSvgShapesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingSvgShapesStage(), options); + } +); + +window.benchmarkClass = BouncingSvgShapesBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js new file mode 100644 index 0000000000..1ef6a091d2 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js @@ -0,0 +1,106 @@ +(function() { + +BouncingTaggedImage = Utilities.createSubclass(BouncingParticle, + function(stage) + { + BouncingParticle.call(this, stage); + + this.element = document.createElement("img"); + this.element.style.width = this.size.x + "px"; + this.element.style.height = this.size.y + "px"; + this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src); + + stage.element.appendChild(this.element); + this._move(); + }, { + + _move: function() + { + this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ(); + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this._move(); + } +}); + +BouncingTaggedImagesStage = Utilities.createSubclass(BouncingParticlesStage, + + function() + { + BouncingParticlesStage.call(this); + }, { + + imageSrcs: [ + "image1", + "image2", + "image3", + "image4", + "image5", + ], + images: [], + + initialize: function(benchmark, options) + { + BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); + + var lastPromise; + var images = this.images; + this.imageSrcs.forEach(function(imageSrc) { + var promise = this._loadImage("resources/" + imageSrc + ".jpg"); + if (!lastPromise) + lastPromise = promise; + else { + lastPromise = lastPromise.then(function(img) { + images.push(img); + return promise; + }); + } + }, this); + + lastPromise.then(function(img) { + images.push(img); + benchmark.readyPromise.resolve(); + }); + }, + + _loadImage: function(src) { + var img = new Image; + var promise = new SimplePromise; + + img.onload = function(e) { + promise.resolve(e.target); + }; + + img.src = src; + return promise; + }, + + createParticle: function() + { + return new BouncingTaggedImage(this); + }, + + particleWillBeRemoved: function(particle) + { + particle.element.remove(); + } +}); + +BouncingTaggedImagesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new BouncingTaggedImagesStage(), options); + }, { + + waitUntilReady: function() { + this.readyPromise = new SimplePromise; + return this.readyPromise; + } +}); + +window.benchmarkClass = BouncingTaggedImagesBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg new file mode 100644 index 0000000000..ea7a4c1303 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg new file mode 100644 index 0000000000..697272dcb0 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg new file mode 100644 index 0000000000..6e5964e7a9 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg new file mode 100644 index 0000000000..806f548c44 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg new file mode 100644 index 0000000000..d7971f6bcb Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html new file mode 100644 index 0000000000..6d5b0bf5e6 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html @@ -0,0 +1,24 @@ + + + + + + + + +
    + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html new file mode 100644 index 0000000000..02264d746f --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html @@ -0,0 +1,51 @@ + + + + + + + + +
    +
    focus
    +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html new file mode 100644 index 0000000000..625882ebef --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html @@ -0,0 +1,26 @@ + + + + + + + + +
    + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html new file mode 100644 index 0000000000..fdc09399c9 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html @@ -0,0 +1,24 @@ + + + + + + + + +
    + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js new file mode 100644 index 0000000000..9fd401eeeb --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js @@ -0,0 +1,66 @@ +(function() { + +BouncingCompositedImage = Utilities.createSubclass(BouncingParticle, + function(stage) + { + BouncingParticle.call(this, stage); + + this.element = document.createElement("img"); + this.element.style.width = this.size.x + "px"; + this.element.style.height = this.size.y + "px"; + this.element.setAttribute("src", stage.imageSrc); + + if (stage.useFilters) + this.element.style.filter = "hue-rotate(" + Stage.randomAngle() + "rad)"; + + stage.element.appendChild(this.element); + this._move(); + }, { + + _move: function() + { + this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) " + this.rotater.rotateZ(); + }, + + animate: function(timeDelta) + { + BouncingParticle.prototype.animate.call(this, timeDelta); + this._move(); + } +}); + +CompositingTransformsStage = Utilities.createSubclass(BouncingParticlesStage, + function() + { + BouncingParticlesStage.call(this); + }, { + + initialize: function(benchmark, options) + { + BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); + + this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg"; + this.useFilters = options["filters"] == "yes"; + }, + + createParticle: function() + { + return new BouncingCompositedImage(this); + }, + + particleWillBeRemoved: function(particle) + { + particle.element.remove(); + } +}); + +CompositedTransformsBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new CompositingTransformsStage(), options); + } +); + +window.benchmarkClass = CompositedTransformsBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js new file mode 100644 index 0000000000..471444b2e7 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js @@ -0,0 +1,73 @@ +(function() { + +DOMParticle = Utilities.createSubclass(Particle, + function(stage) + { + this.element = document.createElement("div"); + stage.element.appendChild(this.element); + + Particle.call(this, stage); + }, { + + reset: function() + { + Particle.prototype.reset.call(this); + + this.position = Stage.randomElementInArray(this.stage.emitLocation); + + var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(100) * this.stage.emissionSpin; + this.velocity = new Point(Math.sin(angle), Math.cos(angle)) + .multiply(Stage.random(.5, 2.5)); + + this.element.style.width = this.size.x + "px"; + this.element.style.height = this.size.y + "px"; + this.stage.colorOffset = (this.stage.colorOffset + 1) % 360; + this.element.style.backgroundColor = "hsl(" + this.stage.colorOffset + ", 70%, 45%)"; + }, + + move: function() + { + this.element.style.transform = "translate(" + this.position.x + "px, " + this.position.y + "px)" + this.rotater.rotateZ(); + } +}); + +DOMParticleStage = Utilities.createSubclass(ParticlesStage, + function() + { + ParticlesStage.call(this); + }, { + + initialize: function(benchmark) + { + ParticlesStage.prototype.initialize.call(this, benchmark); + this.emissionSpin = Stage.random(0, 3); + this.emitSteps = Stage.randomInt(4, 6); + this.emitLocation = [ + new Point(this.size.x * .25, this.size.y * .333), + new Point(this.size.x * .5, this.size.y * .25), + new Point(this.size.x * .75, this.size.y * .333) + ]; + this.colorOffset = Stage.randomInt(0, 359); + }, + + createParticle: function() + { + return new DOMParticle(this); + }, + + willRemoveParticle: function(particle) + { + particle.element.remove(); + } +}); + +DOMParticleBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new DOMParticleStage(), options); + } +); + +window.benchmarkClass = DOMParticleBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js new file mode 100644 index 0000000000..d7722cdff4 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js @@ -0,0 +1,166 @@ +(function() { + +var maxVerticalOffset = 50; +var minimumDiameter = 30; +var centerDiameter = 90; +var sizeVariance = 60; +var travelDistance = 50; + +var opacityMultiplier = 30; + +var FocusElement = Utilities.createClass( + function(stage) + { + var size = minimumDiameter + sizeVariance; + + // Size and blurring are a function of depth. + this._depth = Pseudo.random(); + var distance = Utilities.lerp(this._depth, 0, sizeVariance); + size -= distance; + + var top = Stage.random(0, stage.size.height - size) - stage.maxBlurValue * 3; + var left = Stage.random(0, stage.size.width - size) - stage.maxBlurValue * 3; + + this.container = document.createElement('div'); + this.container.style.width = (size + stage.maxBlurValue * 6) + "px"; + this.container.style.height = (size + stage.maxBlurValue * 6) + "px"; + this.container.style.top = top + "px"; + this.container.style.left = left + "px"; + this.container.style.zIndex = Math.round((1 - this._depth) * 10); + + this.particle = Utilities.createElement("div", {}, this.container); + this.particle.style.width = size + "px"; + this.particle.style.height = size + "px"; + this.particle.style.top = (stage.maxBlurValue * 3) + "px"; + this.particle.style.left = (stage.maxBlurValue * 3) + "px"; + + var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1); + this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; + this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; + }, { + + hide: function() + { + this.container.style.display = "none"; + }, + + show: function() + { + this.container.style.display = "block"; + }, + + animate: function(stage, sinFactor, cosFactor) + { + var top = sinFactor * this._sinMultiplier; + var left = cosFactor * this._cosMultiplier; + + Utilities.setElementPrefixedProperty(this.container, "filter", "blur(" + stage.getBlurValue(this._depth) + "px) opacity(" + stage.getOpacityValue(this._depth) + "%)"); + this.container.style.transform = "translate3d(" + left + "%, " + top + "%, 0)"; + } +}); + +var FocusStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + }, { + + movementDuration: 2500, + focusDuration: 1000, + + centerObjectDepth: 0.0, + + minBlurValue: 1.5, + maxBlurValue: 15, + maxCenterObjectBlurValue: 5, + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + + this._testElements = []; + this._focalPoint = 0.5; + this._offsetIndex = 0; + + this._centerElement = document.getElementById("center-text"); + this._centerElement.style.width = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px"; + this._centerElement.style.height = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px"; + this._centerElement.style.zIndex = Math.round(10 * this.centerObjectDepth); + + var particle = document.querySelector("#center-text div"); + particle.style.width = centerDiameter + "px"; + particle.style.height = centerDiameter + "px"; + particle.style.top = (this.maxCenterObjectBlurValue * 3) + "px"; + particle.style.left = (this.maxCenterObjectBlurValue * 3) + "px"; + + var blur = this.getBlurValue(this.centerObjectDepth, true); + Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + blur + "px)"); + }, + + complexity: function() + { + return 1 + this._offsetIndex; + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this._offsetIndex = Math.max(0, this._offsetIndex + count); + for (var i = this._offsetIndex; i < this._testElements.length; ++i) + this._testElements[i].hide(); + return; + } + + var newIndex = this._offsetIndex + count; + for (var i = this._testElements.length; i < newIndex; ++i) { + var obj = new FocusElement(this); + this._testElements.push(obj); + this.element.appendChild(obj.container); + } + for (var i = this._offsetIndex; i < newIndex; ++i) + this._testElements[i].show(); + this._offsetIndex = newIndex; + }, + + animate: function() + { + var time = this._benchmark.timestamp; + var sinFactor = Math.sin(time / this.movementDuration); + var cosFactor = Math.cos(time / this.movementDuration); + + var focusProgress = 0.5 + 0.5 * Math.sin(time / this.focusDuration); + this._focalPoint = focusProgress; + + Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + this.getBlurValue(this.centerObjectDepth, true) + "px)"); + + for (var i = 0; i < this._offsetIndex; ++i) + this._testElements[i].animate(this, sinFactor, cosFactor); + }, + + getBlurValue: function(depth, isCenter) + { + if (isCenter) + return 1 + Math.abs(depth - this._focalPoint) * (this.maxCenterObjectBlurValue - 1); + + return Utilities.lerp(Math.abs(depth - this._focalPoint), this.minBlurValue, this.maxBlurValue); + }, + + getOpacityValue: function(depth) + { + return Math.max(1, opacityMultiplier * (1 - Math.abs(depth - this._focalPoint))); + }, +}); + +var FocusBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new FocusStage(), options); + } +); + +window.benchmarkClass = FocusBenchmark; + +}()); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js new file mode 100644 index 0000000000..604c973667 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js @@ -0,0 +1,48 @@ +Leaf = Utilities.createSubclass(Particle, + function(stage) + { + this.element = document.createElement("img"); + this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src); + stage.element.appendChild(this.element); + + Particle.call(this, stage); + }, { + + sizeMinimum: 20, + sizeRange: 40, + + reset: function() + { + Particle.prototype.reset.call(this); + this.element.style.width = this.size.x + "px"; + this.element.style.height = this.size.y + "px"; + this._opacity = .01; + this._opacityRate = 0.02 * Stage.random(1, 6); + this._position = new Point(Stage.random(0, this.maxPosition.x), Stage.random(-this.size.height, this.maxPosition.y)); + this._velocity = new Point(Stage.random(-6, -2), .1 * this.size.y + Stage.random(-1, 1)); + }, + + animate: function(timeDelta) + { + this.rotater.next(timeDelta); + + this._position.x += this._velocity.x + 8 * this.stage.focusX; + this._position.y += this._velocity.y; + this._opacity += this._opacityRate; + if (this._opacity > 1) { + this._opacity = 1; + this._opacityRate *= -1; + } else if (this._opacity < 0 || this._position.y > this.stage.size.height) + this.reset(); + + if (this._position.x < -this.size.width || this._position.x > this.stage.size.width) + this._position.x = this._position.x - Math.sign(this._position.x) * (this.size.width + this.stage.size.width); + this.move(); + }, + + move: function() + { + this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); + this.element.style.opacity = this._opacity; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html new file mode 100644 index 0000000000..f86cb44e10 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html new file mode 100644 index 0000000000..e97a7cd79f --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html @@ -0,0 +1,29 @@ + + + + + + + + +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html new file mode 100644 index 0000000000..36b52c9d87 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html @@ -0,0 +1,28 @@ + + + + + + + + +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html new file mode 100644 index 0000000000..ada054025c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html @@ -0,0 +1,25 @@ + + + + + + + + +
    + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html new file mode 100644 index 0000000000..717aff7d8b --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html @@ -0,0 +1,53 @@ + + + + + + + + +
    +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js new file mode 100644 index 0000000000..22002eccd6 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js @@ -0,0 +1,52 @@ +SimpleCanvasStage = Utilities.createSubclass(Stage, + function(canvasObject) + { + Stage.call(this); + this._canvasObject = canvasObject; + this.objects = []; + this.offsetIndex = 0; + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + this.context = this.element.getContext("2d"); + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this.offsetIndex = Math.min(this.offsetIndex - count, this.objects.length); + return; + } + + var newIndex = this.offsetIndex - count; + if (newIndex < 0) { + this.offsetIndex = 0; + newIndex = -newIndex; + for (var i = 0; i < newIndex; ++i) { + if (this._canvasObject.constructor === Array) + this.objects.push(new (Stage.randomElementInArray(this._canvasObject))(this)); + else + this.objects.push(new this._canvasObject(this)); + } + } else + this.offsetIndex = newIndex; + }, + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i) + this.objects[i].draw(context); + }, + + complexity: function() + { + return this.objects.length - this.offsetIndex; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js new file mode 100644 index 0000000000..79fc867082 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js @@ -0,0 +1,311 @@ +(function() { + +// === PAINT OBJECTS === + +CanvasLineSegment = Utilities.createClass( + function(stage) + { + var circle = Stage.randomInt(0, 3); + this._color = ["#e01040", "#10c030", "#744CBA", "#e05010"][circle]; + this._lineWidth = Math.pow(Pseudo.random(), 12) * 20 + 3; + this._omega = Pseudo.random() * 3 + 0.2; + var theta = Stage.randomAngle(); + this._cosTheta = Math.cos(theta); + this._sinTheta = Math.sin(theta); + this._startX = stage.circleRadius * this._cosTheta + stage.circleX[circle]; + this._startY = stage.circleRadius * this._sinTheta + stage.circleY[circle]; + this._length = Math.pow(Pseudo.random(), 8) * stage.lineLengthMaximum + stage.lineMinimum; + this._segmentDirection = Pseudo.random() > 0.5 ? -1 : 1; + }, { + + draw: function(context) + { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + + this._length += Math.sin(Stage.dateCounterValue(100) * this._omega); + + context.beginPath(); + context.moveTo(this._startX, this._startY); + context.lineTo(this._startX + this._segmentDirection * this._length * this._cosTheta, + this._startY + this._segmentDirection * this._length * this._sinTheta); + context.stroke(); + } +}); + +CanvasArc = Utilities.createClass( + function(stage) + { + var maxX = 6, maxY = 3; + var distanceX = stage.size.x / maxX; + var distanceY = stage.size.y / (maxY + 1); + var randY = Stage.randomInt(0, maxY); + var randX = Stage.randomInt(0, maxX - 1 * (randY % 2)); + + this._point = new Point(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + .5)); + + this._radius = 20 + Math.pow(Pseudo.random(), 5) * (Math.min(distanceX, distanceY) / 1.8); + this._startAngle = Stage.randomAngle(); + this._endAngle = Stage.randomAngle(); + this._omega = (Pseudo.random() - 0.5) * 0.3; + this._counterclockwise = Stage.randomBool(); + var colors = ["#101010", "#808080", "#c0c0c0"]; + colors.push(["#e01040", "#10c030", "#e05010"][(randX + Math.ceil(randY / 2)) % 3]); + this._color = colors[Math.floor(Pseudo.random() * colors.length)]; + this._lineWidth = 1 + Math.pow(Pseudo.random(), 5) * 30; + this._doStroke = Stage.randomInt(0, 3) != 0; + }, { + + draw: function(context) + { + this._startAngle += this._omega; + this._endAngle += this._omega / 2; + + if (this._doStroke) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); + context.stroke(); + } else { + context.fillStyle = this._color; + context.beginPath(); + context.lineTo(this._point.x, this._point.y); + context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); + context.lineTo(this._point.x, this._point.y); + context.fill(); + } + } +}); + +// CanvasLinePoint contains no draw() method since it is either moveTo or +// lineTo depending on its index. +CanvasLinePoint = Utilities.createClass( + function(stage) + { + var colors = ["#101010", "#808080", "#c0c0c0", "#101010", "#808080", "#c0c0c0", "#e01040"]; + this.color = Stage.randomElementInArray(colors); + this.width = Math.pow(Pseudo.random(), 5) * 20 + 1; + this.isSplit = Pseudo.random() > 0.95; + + var nextPoint; + if (stage.objects.length) + nextPoint = this.randomPoint(stage, stage.objects[stage.objects.length - 1].coordinate); + else + nextPoint = this.randomPoint(stage, this.gridSize.center); + this.point = nextPoint.point; + this.coordinate = nextPoint.coordinate; + }, { + + gridSize: new Point(80, 40), + offsets: [ + new Point(-4, 0), + new Point(2, 0), + new Point(1, -2), + new Point(1, 2), + ], + + randomPoint: function(stage, startCoordinate) + { + var coordinate = startCoordinate; + if (stage.objects.length) { + var offset = Stage.randomElementInArray(this.offsets); + + coordinate = coordinate.add(offset); + if (coordinate.x < 0 || coordinate.x > this.gridSize.width) + coordinate.x -= offset.x * 2; + if (coordinate.y < 0 || coordinate.y > this.gridSize.height) + coordinate.y -= offset.y * 2; + } + + var x = (coordinate.x + .5) * stage.size.x / (this.gridSize.width + 1); + var y = (coordinate.y + .5) * stage.size.y / (this.gridSize.height + 1); + return { + point: new Point(x, y), + coordinate: coordinate + }; + }, + + draw: function(context) + { + context.lineTo(this.point.x, this.point.y); + } +}); + +CanvasQuadraticSegment = Utilities.createSubclass(CanvasLinePoint, + function(stage) + { + CanvasLinePoint.call(this, stage); + // The chosen point is instead the control point. + this._point2 = this.point; + + // Get another random point for the actual end point of the segment. + var nextPoint = this.randomPoint(stage, this.coordinate); + this.point = nextPoint.point; + this.coordinate = nextPoint.coordinate; + }, { + + draw: function(context) + { + context.quadraticCurveTo(this._point2.x, this._point2.y, this.point.x, this.point.y); + } +}); + +CanvasBezierSegment = Utilities.createSubclass(CanvasLinePoint, + function(stage) + { + CanvasLinePoint.call(this, stage); + // The chosen point is instead the first control point. + this._point2 = this.point; + var nextPoint = this.randomPoint(stage, this.coordinate); + this._point3 = nextPoint.point; + + nextPoint = this.randomPoint(stage, nextPoint.coordinate); + this.point = nextPoint.point; + this.coordinate = nextPoint.coordinate; + }, { + + draw: function(context, off) + { + context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this.point.x, this.point.y); + } +}); + +// === STAGES === + +CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage, + function() + { + SimpleCanvasStage.call(this, CanvasLineSegment); + }, { + + initialize: function(benchmark, options) + { + SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); + this.context.lineCap = options["lineCap"] || "butt"; + this.lineMinimum = 20; + this.lineLengthMaximum = 40; + this.circleRadius = this.size.x / 8 - .4 * (this.lineMinimum + this.lineLengthMaximum); + this.circleX = [ + 5.5 / 32 * this.size.x, + 12.5 / 32 * this.size.x, + 19.5 / 32 * this.size.x, + 26.5 / 32 * this.size.x, + ]; + this.circleY = [ + 2.1 / 3 * this.size.y, + 0.9 / 3 * this.size.y, + 2.1 / 3 * this.size.y, + 0.9 / 3 * this.size.y + ]; + this.halfSize = this.size.multiply(.5); + this.twoFifthsSizeX = this.size.x * .4; + }, + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + + var angle = Stage.dateFractionalValue(3000) * Math.PI * 2; + var dx = this.twoFifthsSizeX * Math.cos(angle); + var dy = this.twoFifthsSizeX * Math.sin(angle); + + var gradient = context.createLinearGradient(this.halfSize.x + dx, this.halfSize.y + dy, this.halfSize.x - dx, this.halfSize.y - dy); + var gradientStep = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(5000) * Math.PI * 2); + var colorStopStep = Utilities.lerp(gradientStep, -.1, .1); + var brightnessStep = Math.round(Utilities.lerp(gradientStep, 32, 64)); + var color1Step = "rgba(" + brightnessStep + "," + brightnessStep + "," + (brightnessStep << 1) + ",.4)"; + var color2Step = "rgba(" + (brightnessStep << 1) + "," + (brightnessStep << 1) + "," + brightnessStep + ",.4)"; + gradient.addColorStop(0, color1Step); + gradient.addColorStop(.2 + colorStopStep, color1Step); + gradient.addColorStop(.8 - colorStopStep, color2Step); + gradient.addColorStop(1, color2Step); + + context.lineWidth = 15; + for(var i = 0; i < 4; i++) { + context.strokeStyle = ["#e01040", "#10c030", "#744CBA", "#e05010"][i]; + context.fillStyle = ["#70051d", "#016112", "#2F0C6E", "#702701"][i]; + context.beginPath(); + context.arc(this.circleX[i], this.circleY[i], this.circleRadius, 0, Math.PI*2); + context.stroke(); + context.fill(); + context.fillStyle = gradient; + context.fill(); + } + + for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i) + this.objects[i].draw(context); + } +}); + +CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasStage, + function() + { + SimpleCanvasStage.call(this, [CanvasLinePoint, CanvasLinePoint, CanvasQuadraticSegment, CanvasBezierSegment]); + }, { + + initialize: function(benchmark, options) + { + SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); + this.context.lineJoin = options["lineJoin"] || "bevel"; + this.context.lineCap = options["lineCap"] || "butt"; + }, + + animate: function() { + var context = this.context; + + context.clearRect(0, 0, this.size.x, this.size.y); + context.beginPath(); + for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i) { + var object = this.objects[i]; + if (i == this.offsetIndex) { + context.lineWidth = object.width; + context.strokeStyle = object.color; + context.beginPath(); + context.moveTo(object.point.x, object.point.y); + } else { + object.draw(context); + + if (object.isSplit) { + context.stroke(); + + context.lineWidth = object.width; + context.strokeStyle = object.color; + context.beginPath(); + context.moveTo(object.point.x, object.point.y); + } + + if (Pseudo.random() > 0.995) + object.isSplit = !object.isSplit; + } + } + context.stroke(); + } +}); + +// === BENCHMARK === + +CanvasPathBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + var stage; + switch (options["pathType"]) { + case "line": + stage = new CanvasLineSegmentStage(); + break; + case "linePath": + stage = new CanvasLinePathStage(); + break; + case "arcs": + stage = new SimpleCanvasStage(CanvasArc); + break; + } + + Benchmark.call(this, stage, options); + } +); + +window.benchmarkClass = CanvasPathBenchmark; + +})(); \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg new file mode 100644 index 0000000000..3f94e7a4b2 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png new file mode 100644 index 0000000000..e513ce11e3 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg new file mode 100644 index 0000000000..e3c7611d2a --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png new file mode 100644 index 0000000000..81f9c1641d Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg new file mode 100644 index 0000000000..68860efa86 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png new file mode 100644 index 0000000000..790e3dcfca Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg new file mode 100644 index 0000000000..646ddf446c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png new file mode 100644 index 0000000000..e2652096dc Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js new file mode 100644 index 0000000000..04842e744e --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js @@ -0,0 +1,129 @@ +(function() { + +var minimumDiameter = 30; +var sizeVariance = 20; +var travelDistance = 50; + +var minBlurValue = 1; +var maxBlurValue = 10; + +var opacityMultiplier = 30; +var focusDuration = 1000; +var movementDuration = 2500; + +var FocusElement = Utilities.createClass( + function(stage) + { + var size = minimumDiameter + sizeVariance; + + // Size and blurring are a function of depth. + this._depth = Pseudo.random(); + var distance = Utilities.lerp(this._depth, 0, sizeVariance); + size -= distance; + + var top = Stage.random(0, stage.size.height - size); + var left = Stage.random(0, stage.size.width - size); + + this.particle = document.createElement("div"); + this.particle.style.width = size + "px"; + this.particle.style.height = size + "px"; + this.particle.style.top = top + "px"; + this.particle.style.left = left + "px"; + this.particle.style.zIndex = Math.round((1 - this._depth) * 10); + + var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1); + this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; + this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; + + this.animate(stage, 0, 0); + }, { + + hide: function() + { + this.particle.style.display = "none"; + }, + + show: function() + { + this.particle.style.display = "block"; + }, + + animate: function(stage, sinFactor, cosFactor) + { + var top = sinFactor * this._sinMultiplier; + var left = cosFactor * this._cosMultiplier; + var distance = Math.abs(this._depth - stage.focalPoint); + var blur = Utilities.lerp(distance, minBlurValue, maxBlurValue); + var opacity = Math.max(5, opacityMultiplier * (1 - distance)); + + Utilities.setElementPrefixedProperty(this.particle, "filter", "blur(" + blur + "px) opacity(" + opacity + "%)"); + this.particle.style.transform = "translate3d(" + left + "%, " + top + "%, 0)"; + } +}); + +var FocusStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + + this._testElements = []; + this._offsetIndex = 0; + this.focalPoint = 0.5; + }, + + complexity: function() + { + return this._offsetIndex; + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this._offsetIndex = Math.max(0, this._offsetIndex + count); + for (var i = this._offsetIndex; i < this._testElements.length; ++i) + this._testElements[i].hide(); + return; + } + + var newIndex = this._offsetIndex + count; + for (var i = this._testElements.length; i < newIndex; ++i) { + var obj = new FocusElement(this); + this._testElements.push(obj); + this.element.appendChild(obj.particle); + } + for (var i = this._offsetIndex; i < newIndex; ++i) + this._testElements[i].show(); + this._offsetIndex = newIndex; + }, + + animate: function() + { + var time = this._benchmark.timestamp; + var sinFactor = Math.sin(time / movementDuration); + var cosFactor = Math.cos(time / movementDuration); + + this.focalPoint = 0.5 + 0.5 * Math.sin(time / focusDuration); + + for (var i = 0; i < this._offsetIndex; ++i) + this._testElements[i].animate(this, sinFactor, cosFactor); + } +}); + +var FocusBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new FocusStage(), options); + } +); + +window.benchmarkClass = FocusBenchmark; + +}()); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js new file mode 100644 index 0000000000..6de5d068bb --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js @@ -0,0 +1,181 @@ +(function() { + +var ImageDataStage = Utilities.createSubclass(Stage, + function() { + Stage.call(this); + + this.testElements = []; + this._offsetIndex = 0; + }, { + + imageWidth: 50, + imageHeight: 50, + pixelStride: 4, + rowStride: 200, + weightNegativeThreshold: 0.04, + weightPositiveThreshold: 0.96, + imageSrcs: [ + "compass", + "console", + "contribute", + "debugger", + "inspector", + "layout", + "performance", + "script", + "shortcuts", + "standards", + "storage", + "styles", + "timeline" + ], + images: [], + + initialize: function(benchmark) + { + Stage.prototype.initialize.call(this, benchmark); + + var lastPromise; + var images = this.images; + this.imageSrcs.forEach(function(imageSrc) { + var promise = this._loadImage("resources/" + imageSrc + ".svg"); + if (!lastPromise) + lastPromise = promise; + else { + lastPromise = lastPromise.then(function(img) { + images.push(img); + return promise; + }); + } + }, this); + + lastPromise.then(function(img) { + images.push(img); + benchmark.readyPromise.resolve(); + }.bind(this)); + }, + + _loadImage: function(src) { + var img = new Image; + var promise = new SimplePromise; + + img.addEventListener('load', function onImageLoad(e) { + img.removeEventListener('load', onImageLoad); + promise.resolve(img); + }); + + img.src = src; + return promise; + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this._offsetIndex = Math.max(this._offsetIndex + count, 0); + for (var i = this._offsetIndex; i < this.testElements.length; ++i) + this.testElements[i].style.display = "none"; + return; + } + + this._offsetIndex = this._offsetIndex + count; + var index = Math.min(this._offsetIndex, this.testElements.length); + for (var i = 0; i < index; ++i) { + this.testElements[i].style.display = "block"; + this._refreshElement(this.testElements[i]); + } + if (this._offsetIndex <= this.testElements.length) + return; + + index = this._offsetIndex - this.testElements.length; + for (var i = 0; i < index; ++i) { + var element = this._createTestElement(); + this.testElements.push(element); + this.element.appendChild(element); + } + }, + + _createTestElement: function() { + var element = document.createElement('canvas'); + element.width = this.imageWidth; + element.height = this.imageHeight; + element.style.width = this.imageWidth + 'px'; + element.style.height = this.imageHeight + 'px'; + + this._refreshElement(element); + return element; + }, + + _refreshElement: function(element) { + var top = Stage.randomInt(0, Math.floor((this.size.height - this.imageHeight) / this.imageHeight)) * this.imageHeight; + var left = Stage.randomInt(0, Math.floor((this.size.width - this.imageWidth) / this.imageWidth)) * this.imageWidth; + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + }, + + animate: function(timeDelta) { + for (var i = 0; i < this._offsetIndex; ++i) { + var element = this.testElements[i]; + var context = element.getContext("2d"); + + // Get image data + var imageData = context.getImageData(0, 0, this.imageWidth, this.imageHeight); + + var didDraw = false, + neighborPixelIndex, + dataLen = imageData.data.length; + for (var j = 0; j < dataLen; j += this.pixelStride) { + if (imageData.data[j + 3] === 0) + continue; + + // get random neighboring pixel color + neighborPixelIndex = this._getRandomNeighboringPixelIndex(j, dataLen); + + // Update the RGB data + imageData.data[j] = imageData.data[neighborPixelIndex]; + imageData.data[j + 1] = imageData.data[neighborPixelIndex + 1]; + imageData.data[j + 2] = imageData.data[neighborPixelIndex + 2]; + imageData.data[j + 3] = imageData.data[neighborPixelIndex + 3]; + didDraw = true; + } + + if (didDraw) + context.putImageData(imageData, 0, 0); + else { + this._refreshElement(element); + element.getContext("2d").drawImage(Stage.randomElementInArray(this.images), 0, 0, this.imageWidth, this.imageHeight); + } + } + }, + + _getRandomNeighboringPixelIndex: function(pixelIdx, pixelArrayLength) + { + var xOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold)); + var yOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold)); + return (pixelIdx + this.pixelStride * xOffset + this.rowStride * yOffset) % pixelArrayLength; + }, + + complexity: function() + { + return this._offsetIndex; + } +}); + +var ImageDataBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new ImageDataStage(), options); + }, { + + waitUntilReady: function() { + this.readyPromise = new SimplePromise; + return this.readyPromise; + } +}); + +window.benchmarkClass = ImageDataBenchmark; + +}()); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg new file mode 100644 index 0000000000..68cc413052 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png new file mode 100644 index 0000000000..26d1a7d592 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg new file mode 100644 index 0000000000..73db97eb46 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png new file mode 100644 index 0000000000..5b1ec2806b Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js new file mode 100644 index 0000000000..7a049836ff --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js @@ -0,0 +1,135 @@ +Leaf = Utilities.createSubclass(Particle, + function(stage) + { + this.element = document.createElement("img"); + this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src); + var sizeString = this.sizeMinimum + "px"; + this.element.style.width = sizeString; + this.element.style.height = sizeString; + stage.element.appendChild(this.element); + + Particle.call(this, stage); + }, { + + sizeMinimum: 25, + sizeRange: 0, + + reset: function() + { + Particle.prototype.reset.call(this); + this._life = Stage.randomInt(20, 100); + this._position = new Point(Stage.random(0, this.maxPosition.x), Stage.random(-this.size.height, this.maxPosition.y)); + this._velocity = new Point(Stage.random(-6, -2), .1 * this.size.y + Stage.random(-1, 1)); + }, + + animate: function(timeDelta) + { + this.rotater.next(timeDelta); + + this._position.x += this._velocity.x + 8 * this.stage.focusX; + this._position.y += this._velocity.y; + + this._life--; + if (!this._life || this._position.y > this.stage.size.height) + this.reset(); + + if (this._position.x < -this.size.width || this._position.x > this.stage.size.width) + this._position.x = this._position.x - Math.sign(this._position.x) * (this.size.width + this.stage.size.width); + this.move(); + }, + + move: function() + { + this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); + } +}); + +Utilities.extendObject(ParticlesStage.prototype, { + + imageSrcs: [ + "compass", + "console", + "contribute", + "debugger", + "inspector", + "layout", + "performance", + "script", + "shortcuts", + "standards", + "storage", + "styles", + "timeline" + ], + images: [], + + initialize: function(benchmark) + { + Stage.prototype.initialize.call(this, benchmark); + + var lastPromise; + var images = this.images; + this.imageSrcs.forEach(function(imageSrc) { + var promise = this._loadImage("../master/resources/" + imageSrc + "100.png"); + if (!lastPromise) + lastPromise = promise; + else { + lastPromise = lastPromise.then(function(img) { + images.push(img); + return promise; + }); + } + }, this); + + lastPromise.then(function(img) { + images.push(img); + benchmark.readyPromise.resolve(); + }); + }, + + _loadImage: function(src) { + var img = new Image; + var promise = new SimplePromise; + + img.onload = function(e) { + promise.resolve(e.target); + }; + + img.src = src; + return promise; + }, + + animate: function(timeDelta) + { + this.focusX = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(10000) * Math.PI * 2); + timeDelta /= 4; + this.particles.forEach(function(particle) { + particle.animate(timeDelta); + }); + }, + + createParticle: function() + { + return new Leaf(this); + }, + + willRemoveParticle: function(particle) + { + particle.element.remove(); + } +}); + +LeavesBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new ParticlesStage(), options); + }, { + + waitUntilReady: function() { + this.readyPromise = new SimplePromise; + return this.readyPromise; + } + +}); + +window.benchmarkClass = LeavesBenchmark; diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js new file mode 100644 index 0000000000..e93cfbb5b9 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js @@ -0,0 +1,119 @@ +(function() { + +var MultiplyStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + this.tiles = []; + this._offsetIndex = 0; + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + var tileSize = Math.round(this.size.height / 25); + + // Fill the scene with elements + var x = Math.round((this.size.width - tileSize) / 2); + var y = Math.round((this.size.height - tileSize) / 2); + var tileStride = tileSize; + var direction = 0; + var spiralCounter = 2; + var nextIndex = 1; + var maxSide = Math.floor(y / tileStride) * 2 + 1; + this._centerSpiralCount = maxSide * maxSide; + for (var i = 0; i < this._centerSpiralCount; ++i) { + this._addTile(x, y, tileSize, Stage.randomInt(0, 359)); + + if (i == nextIndex) { + direction = (direction + 1) % 4; + spiralCounter++; + nextIndex += spiralCounter >> 1; + } + if (direction == 0) + x += tileStride; + else if (direction == 1) + y -= tileStride; + else if (direction == 2) + x -= tileStride; + else + y += tileStride; + } + + this._sidePanelCount = maxSide * Math.floor((this.size.width - x) / tileStride) * 2; + for (var i = 0; i < this._sidePanelCount; ++i) { + var sideX = x + Math.floor(Math.floor(i / maxSide) / 2) * tileStride; + var sideY = y - tileStride * (i % maxSide); + + if (Math.floor(i / maxSide) % 2 == 1) + sideX = this.size.width - sideX - tileSize + 1; + this._addTile(sideX, sideY, tileSize, Stage.randomInt(0, 359)); + } + }, + + _addTile: function(x, y, tileSize, rotateDeg) + { + var tile = Utilities.createElement("div", { class: "div-" + Stage.randomInt(0,6) }, this.element); + var halfTileSize = tileSize / 2; + tile.style.left = x + 'px'; + tile.style.top = y + 'px'; + tile.style.width = tileSize + 'px'; + tile.style.height = tileSize + 'px'; + tile.style.visibility = "hidden"; + + var distance = 1 / tileSize * this.size.multiply(0.5).subtract(new Point(x + halfTileSize, y + halfTileSize)).length(); + this.tiles.push({ + element: tile, + rotate: rotateDeg, + step: Math.max(3, distance / 1.5), + distance: distance, + active: false + }); + }, + + complexity: function() + { + return this._offsetIndex; + }, + + tune: function(count) + { + this._offsetIndex = Math.max(0, Math.min(this._offsetIndex + count, this.tiles.length)); + this._distanceFactor = 1.5 * (1 - 0.5 * Math.max(this._offsetIndex - this._centerSpiralCount, 0) / this._sidePanelCount) / Math.sqrt(this._offsetIndex); + }, + + animate: function() + { + var progress = this._benchmark.timestamp % 10000 / 10000; + var bounceProgress = Math.sin(2 * Math.abs( 0.5 - progress)); + var l = Utilities.lerp(bounceProgress, 20, 50); + var hslPrefix = "hsla(" + Utilities.lerp(progress, 0, 360) + ",100%,"; + + for (var i = 0; i < this._offsetIndex; ++i) { + var tile = this.tiles[i]; + tile.active = true; + tile.element.style.visibility = ""; + tile.rotate += tile.step; + tile.element.style.transform = "rotate(" + tile.rotate + "deg)"; + + var influence = Math.max(.01, 1 - (tile.distance * this._distanceFactor)); + tile.element.style.backgroundColor = hslPrefix + l * Math.tan(influence / 1.25) + "%," + influence + ")"; + } + + for (var i = this._offsetIndex; i < this.tiles.length && this.tiles[i].active; ++i) { + this.tiles[i].active = false; + this.tiles[i].element.style.visibility = "hidden"; + } + } +}); + +var MultiplyBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new MultiplyStage(), options); + } +); + +window.benchmarkClass = MultiplyBenchmark; + +}()); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js new file mode 100644 index 0000000000..cf474e4142 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js @@ -0,0 +1,112 @@ +function Particle(stage) +{ + this.stage = stage; + this.rotater = Stage.randomRotater(); + this.reset(); + this.move(); +} + +Particle.prototype = +{ + sizeMinimum: 40, + sizeRange: 10, + + reset: function() + { + var randSize = Math.round(Math.pow(Pseudo.random(), 4) * this.sizeRange + this.sizeMinimum); + this.size = new Point(randSize, randSize); + this.minPosition = this.size.center; + this.maxPosition = this.stage.size.subtract(this.minPosition); + }, + + animate: function(timeDelta) + { + this.rotater.next(timeDelta); + + this.position = this.position.add(this.velocity.multiply(timeDelta)); + this.velocity.y += 0.03; + + // If particle is going to move off right side + if (this.position.x > this.maxPosition.x) { + if (this.velocity.x > 0) + this.velocity.x *= -1; + this.position.x = this.maxPosition.x; + } else if (this.position.x < this.minPosition.x) { + // If particle is going to move off left side + if (this.velocity.x < 0) + this.velocity.x *= -1; + this.position.x = this.minPosition.x; + } + + // If particle is going to move off bottom side + if (this.position.y > this.maxPosition.y) { + // Adjust direction but maintain magnitude + var magnitude = this.velocity.length(); + this.velocity.x *= 1.5 + .005 * this.size.x; + this.velocity = this.velocity.normalize().multiply(magnitude); + if (Math.abs(this.velocity.y) < 0.7) + this.reset(); + else { + if (this.velocity.y > 0) + this.velocity.y *= -0.999; + this.position.y = this.maxPosition.y; + } + } else if (this.position.y < this.minPosition.y) { + // If particle is going to move off top side + var magnitude = this.velocity.length(); + this.velocity.x *= 1.5 + .005 * this.size.x; + this.velocity = this.velocity.normalize().multiply(magnitude); + if (this.velocity.y < 0) + this.velocity.y *= -0.998; + this.position.y = this.minPosition.y; + } + + this.move(); + }, + + move: function() + { + } +} + +ParticlesStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + this.particles = []; + }, { + + animate: function(timeDelta) + { + timeDelta /= 4; + this.particles.forEach(function(particle) { + particle.animate(timeDelta); + }); + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count > 0) { + for (var i = 0; i < count; ++i) + this.particles.push(this.createParticle()); + return; + } + + count = Math.min(-count, this.particles.length); + + if (typeof(this.willRemoveParticle) == "function") { + for (var i = 0; i < count; ++i) + this.willRemoveParticle(this.particles[i]); + } + + this.particles.splice(0, count); + }, + + complexity: function() + { + return this.particles.length; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg new file mode 100644 index 0000000000..37c4e952c1 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png new file mode 100644 index 0000000000..3f8a187596 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg new file mode 100644 index 0000000000..5e3f9c1b03 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png new file mode 100644 index 0000000000..c2ea55ead7 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg new file mode 100644 index 0000000000..edaa84963b --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png new file mode 100644 index 0000000000..aeb23e0a40 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg new file mode 100644 index 0000000000..ac1e6934d8 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png new file mode 100644 index 0000000000..ff386ff163 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg new file mode 100644 index 0000000000..c34a9ed255 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png new file mode 100644 index 0000000000..bc59d92fcf Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg new file mode 100644 index 0000000000..f50cff7d6d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png new file mode 100644 index 0000000000..7bc9fffe9c Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js new file mode 100644 index 0000000000..2ce24b56f1 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js @@ -0,0 +1,111 @@ +(function() { + +SVGParticle = Utilities.createSubclass(Particle, + function(stage) + { + var shapeId = "#shape-" + Stage.randomInt(1, stage.particleTypeCount); + this.isClipPath = Stage.randomBool(); + if (this.isClipPath) { + this.element = Utilities.createSVGElement("rect", { + x: 0, + y: 0, + "clip-path": "url(" + shapeId + ")" + }, {}, stage.element); + } else { + var shapePath = document.querySelector(shapeId + " path"); + this.element = shapePath.cloneNode(); + stage.element.appendChild(this.element); + } + + this.gradient = document.getElementById("default-gradient").cloneNode(true); + this.gradient.id = "gradient-" + stage.gradientsCounter++; + stage.gradientsDefs.appendChild(this.gradient); + this.element.setAttribute("fill", "url(#" + this.gradient.id + ")"); + + Particle.call(this, stage); + }, { + + sizeMinimum: 30, + sizeRange: 40, + + reset: function() + { + Particle.prototype.reset.call(this); + + this.position = Stage.randomElementInArray(this.stage.emitLocation); + + var velocityMagnitude = Stage.random(.5, 2.5); + var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(1000) * this.stage.emissionSpin + velocityMagnitude; + this.velocity = new Point(Math.sin(angle), Math.cos(angle)) + .multiply(velocityMagnitude); + + if (this.isClipPath) { + this.element.setAttribute("width", this.size.x); + this.element.setAttribute("height", this.size.y); + this.transformSuffix = " translate(-" + this.size.center.x + ",-" + this.size.center.y + ")"; + } else + this.transformSuffix = " scale(" + this.size.x + ") translate(-.5,-.5)"; + + this.stage.colorOffset = (this.stage.colorOffset + .5) % 360; + + var transform = this.stage.element.createSVGTransform(); + transform.setRotate(Stage.randomInt(0, 359), 0, 0); + this.gradient.gradientTransform.baseVal.initialize(transform); + + var stops = this.gradient.querySelectorAll("stop"); + stops[0].setAttribute("stop-color", "hsl(" + this.stage.colorOffset + ", 70%, 45%)"); + stops[1].setAttribute("stop-color", "hsl(" + ((this.stage.colorOffset + Stage.randomInt(50,100)) % 360) + ", 70%, 65%)"); + }, + + move: function() + { + this.element.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.rotater.rotate(Point.zero) + this.transformSuffix); + } +}); + +SVGParticleStage = Utilities.createSubclass(ParticlesStage, + function() + { + ParticlesStage.call(this); + }, { + + initialize: function(benchmark) + { + ParticlesStage.prototype.initialize.call(this, benchmark); + this.emissionSpin = Stage.random(0, 3); + this.emitSteps = Stage.randomInt(4, 6); + this.emitLocation = [ + new Point(this.size.x * .25, this.size.y * .333), + new Point(this.size.x * .5, this.size.y * .25), + new Point(this.size.x * .75, this.size.y * .333) + ]; + this.colorOffset = Stage.randomInt(0, 359); + + this.particleTypeCount = document.querySelectorAll(".shape").length; + this.gradientsDefs = document.getElementById("gradients"); + this.gradientsCounter = 0; + }, + + createParticle: function() + { + return new SVGParticle(this); + }, + + willRemoveParticle: function(particle) + { + particle.element.remove(); + if (particle.gradient) + particle.gradient.remove(); + } +}); + +SVGParticleBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new SVGParticleStage(), options); + } +); + +window.benchmarkClass = SVGParticleBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js new file mode 100644 index 0000000000..c7ebe464b3 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js @@ -0,0 +1,116 @@ +(function() { + +var TextStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + + this.testElements = []; + this._offsetIndex = 0; + }, { + + shadowFalloff: new UnitBezier(new Point(0.015, 0.750), new Point(0.755, 0.235)), + shimmerAverage: 0, + shimmerMax: 0.5, + millisecondsPerRotation: 1000 / (.26 * Math.PI * 2), + particleDistanceX: 1.5, + particleDistanceY: .5, + lightnessMin: 13, + lightnessMax: 94, + gradients: [ + [10, 176, 176, 209, 148, 140], + [171, 120, 154, 245, 196, 154], + [224, 99, 99, 71, 134, 148], + [101, 100, 117, 80, 230, 175], + [232, 165, 30, 69, 186, 172] + ], + + initialize: function(benchmark) + { + Stage.prototype.initialize.call(this, benchmark); + + this._template = document.getElementById("template"); + this._offset = this.size.subtract(Point.elementClientSize(this._template)).multiply(.5); + this._template.style.left = this._offset.width + "px"; + this._template.style.top = this._offset.height + "px"; + + this._stepProgress = 0; + }, + + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this._offsetIndex = Math.max(this._offsetIndex + count, 0); + for (var i = this._offsetIndex; i < this.testElements.length; ++i) + this.testElements[i].style.visibility = "hidden"; + + this._stepProgress = 1 / this._offsetIndex; + return; + } + + this._offsetIndex = this._offsetIndex + count; + this._stepProgress = 1 / this._offsetIndex; + + var index = Math.min(this._offsetIndex, this.testElements.length); + for (var i = 0; i < index; ++i) + this.testElements[i].style.visibility = "visible"; + + if (this._offsetIndex <= this.testElements.length) + return; + + for (var i = this.testElements.length; i < this._offsetIndex; ++i) { + var clone = this._template.cloneNode(true); + this.testElements.push(clone); + this.element.insertBefore(clone, this.element.firstChild); + } + }, + + animate: function(timeDelta) { + var angle = Stage.dateCounterValue(this.millisecondsPerRotation); + + var progress = 0; + var stepX = Math.sin(angle) * this.particleDistanceX; + var stepY = Math.cos(angle) * this.particleDistanceY; + var x = -stepX * 3; + var y = -stepY * 3; + var gradient = this.gradients[Math.floor(angle/(Math.PI * 2)) % this.gradients.length]; + var offset = Stage.dateCounterValue(200); + this._template.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)"; + for (var i = 0; i < this._offsetIndex; ++i) { + var element = this.testElements[i]; + + var colorProgress = this.shadowFalloff.solve(progress); + var shimmer = Math.sin(offset - colorProgress); + colorProgress = Math.max(Math.min(colorProgress + Utilities.lerp(shimmer, this.shimmerAverage, this.shimmerMax), 1), 0); + var r = Math.round(Utilities.lerp(colorProgress, gradient[0], gradient[3])); + var g = Math.round(Utilities.lerp(colorProgress, gradient[1], gradient[4])); + var b = Math.round(Utilities.lerp(colorProgress, gradient[2], gradient[5])); + element.style.color = "rgb(" + r + "," + g + "," + b + ")"; + + x += stepX; + y += stepY; + element.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)"; + + progress += this._stepProgress; + } + }, + + complexity: function() + { + return 1 + this._offsetIndex; + } +}); + +var TextBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new TextStage(), options); + } +); + +window.benchmarkClass = TextBenchmark; + +}()); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg new file mode 100644 index 0000000000..cd1e8a4e20 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png new file mode 100644 index 0000000000..b9839f8447 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html new file mode 100644 index 0000000000..46a19369da --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html new file mode 100644 index 0000000000..5e94b8ce95 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html @@ -0,0 +1,82 @@ + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    σχέδιο设计suunnittelu
    designдизайнتصميم
    디자인conceptionデザイン
    konstruktionעיצובdiseño
    +
    +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js new file mode 100644 index 0000000000..b9776d571e --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js @@ -0,0 +1,934 @@ +Sampler = Utilities.createClass( + function(seriesCount, expectedSampleCount, processor) + { + this._processor = processor; + + this.samples = []; + for (var i = 0; i < seriesCount; ++i) { + var array = new Array(expectedSampleCount); + array.fill(0); + this.samples[i] = array; + } + this.sampleCount = 0; + }, { + + record: function() { + // Assume that arguments.length == this.samples.length + for (var i = 0; i < arguments.length; i++) { + this.samples[i][this.sampleCount] = arguments[i]; + } + ++this.sampleCount; + }, + + processSamples: function() + { + var results = {}; + + // Remove unused capacity + this.samples = this.samples.map(function(array) { + return array.slice(0, this.sampleCount); + }, this); + + this._processor.processSamples(results); + + return results; + } +}); + +Controller = Utilities.createClass( + function(benchmark, options) + { + // Initialize timestamps relative to the start of the benchmark + // In start() the timestamps are offset by the start timestamp + this._startTimestamp = 0; + this._endTimestamp = options["test-interval"]; + // Default data series: timestamp, complexity, estimatedFrameLength + var sampleSize = options["sample-capacity"] || (60 * options["test-interval"] / 1000); + this._sampler = new Sampler(options["series-count"] || 3, sampleSize, this); + this._marks = {}; + + this._frameLengthEstimator = new SimpleKalmanEstimator(options["kalman-process-error"], options["kalman-measurement-error"]); + this._isFrameLengthEstimatorEnabled = true; + + // Length of subsequent intervals; a value of 0 means use no intervals + this.intervalSamplingLength = 100; + + this.initialComplexity = 1; + }, { + + set isFrameLengthEstimatorEnabled(enabled) { + this._isFrameLengthEstimatorEnabled = enabled; + }, + + start: function(startTimestamp, stage) + { + this._startTimestamp = startTimestamp; + this._endTimestamp += startTimestamp; + this._previousTimestamp = startTimestamp; + this._measureAndResetInterval(startTimestamp); + this.recordFirstSample(startTimestamp, stage); + }, + + recordFirstSample: function(startTimestamp, stage) + { + this._sampler.record(startTimestamp, stage.complexity(), -1); + this.mark(Strings.json.samplingStartTimeOffset, startTimestamp); + }, + + mark: function(comment, timestamp, data) { + data = data || {}; + data.time = timestamp; + data.index = this._sampler.sampleCount; + this._marks[comment] = data; + }, + + containsMark: function(comment) { + return comment in this._marks; + }, + + _measureAndResetInterval: function(currentTimestamp) + { + var sampleCount = this._sampler.sampleCount; + var averageFrameLength = 0; + + if (this._intervalEndTimestamp) { + var intervalStartTimestamp = this._sampler.samples[0][this._intervalStartIndex]; + averageFrameLength = (currentTimestamp - intervalStartTimestamp) / (sampleCount - this._intervalStartIndex); + } + + this._intervalStartIndex = sampleCount; + this._intervalEndTimestamp = currentTimestamp + this.intervalSamplingLength; + + return averageFrameLength; + }, + + update: function(timestamp, stage) + { + var lastFrameLength = timestamp - this._previousTimestamp; + this._previousTimestamp = timestamp; + + var frameLengthEstimate = -1, intervalAverageFrameLength = -1; + var didFinishInterval = false; + if (!this.intervalSamplingLength) { + if (this._isFrameLengthEstimatorEnabled) { + this._frameLengthEstimator.sample(lastFrameLength); + frameLengthEstimate = this._frameLengthEstimator.estimate; + } + } else if (timestamp >= this._intervalEndTimestamp) { + var intervalStartTimestamp = this._sampler.samples[0][this._intervalStartIndex]; + intervalAverageFrameLength = this._measureAndResetInterval(timestamp); + if (this._isFrameLengthEstimatorEnabled) { + this._frameLengthEstimator.sample(intervalAverageFrameLength); + frameLengthEstimate = this._frameLengthEstimator.estimate; + } + didFinishInterval = true; + this.didFinishInterval(timestamp, stage, intervalAverageFrameLength); + } + + this._sampler.record(timestamp, stage.complexity(), frameLengthEstimate); + this.tune(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength); + }, + + didFinishInterval: function(timestamp, stage, intervalAverageFrameLength) + { + }, + + tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength) + { + }, + + shouldStop: function(timestamp) + { + return timestamp > this._endTimestamp; + }, + + results: function() + { + return this._sampler.processSamples(); + }, + + _processComplexitySamples: function(complexitySamples, complexityAverageSamples) + { + complexityAverageSamples.addField(Strings.json.complexity, 0); + complexityAverageSamples.addField(Strings.json.frameLength, 1); + complexityAverageSamples.addField(Strings.json.measurements.stdev, 2); + + complexitySamples.sort(function(a, b) { + return complexitySamples.getFieldInDatum(a, Strings.json.complexity) - complexitySamples.getFieldInDatum(b, Strings.json.complexity); + }); + + // Samples averaged based on complexity + var currentComplexity = -1; + var experimentAtComplexity; + function addSample() { + var mean = experimentAtComplexity.mean(); + var stdev = experimentAtComplexity.standardDeviation(); + + var averageSample = complexityAverageSamples.createDatum(); + complexityAverageSamples.push(averageSample); + complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.complexity, currentComplexity); + complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.frameLength, mean); + complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.measurements.stdev, stdev); + } + complexitySamples.forEach(function(sample) { + var sampleComplexity = complexitySamples.getFieldInDatum(sample, Strings.json.complexity); + if (sampleComplexity != currentComplexity) { + if (currentComplexity > -1) + addSample(); + + currentComplexity = sampleComplexity; + experimentAtComplexity = new Experiment; + } + experimentAtComplexity.sample(complexitySamples.getFieldInDatum(sample, Strings.json.frameLength)); + }); + // Finish off the last one + addSample(); + }, + + processSamples: function(results) + { + var complexityExperiment = new Experiment; + var smoothedFrameLengthExperiment = new Experiment; + + var samples = this._sampler.samples; + + for (var markName in this._marks) + this._marks[markName].time -= this._startTimestamp; + results[Strings.json.marks] = this._marks; + + results[Strings.json.samples] = {}; + + var controllerSamples = new SampleData; + results[Strings.json.samples][Strings.json.controller] = controllerSamples; + + controllerSamples.addField(Strings.json.time, 0); + controllerSamples.addField(Strings.json.complexity, 1); + controllerSamples.addField(Strings.json.frameLength, 2); + controllerSamples.addField(Strings.json.smoothedFrameLength, 3); + + var complexitySamples = new SampleData(controllerSamples.fieldMap); + results[Strings.json.samples][Strings.json.complexity] = complexitySamples; + + samples[0].forEach(function(timestamp, i) { + var sample = controllerSamples.createDatum(); + controllerSamples.push(sample); + complexitySamples.push(sample); + + // Represent time in milliseconds + controllerSamples.setFieldInDatum(sample, Strings.json.time, timestamp - this._startTimestamp); + controllerSamples.setFieldInDatum(sample, Strings.json.complexity, samples[1][i]); + + if (i == 0) + controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, 1000/60); + else + controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, timestamp - samples[0][i - 1]); + + if (samples[2][i] != -1) + controllerSamples.setFieldInDatum(sample, Strings.json.smoothedFrameLength, samples[2][i]); + }, this); + + var complexityAverageSamples = new SampleData; + results[Strings.json.samples][Strings.json.complexityAverage] = complexityAverageSamples; + this._processComplexitySamples(complexitySamples, complexityAverageSamples); + } +}); + +FixedController = Utilities.createSubclass(Controller, + function(benchmark, options) + { + Controller.call(this, benchmark, options); + this.initialComplexity = options["complexity"]; + this.intervalSamplingLength = 0; + } +); + +StepController = Utilities.createSubclass(Controller, + function(benchmark, options) + { + Controller.call(this, benchmark, options); + this.initialComplexity = options["complexity"]; + this.intervalSamplingLength = 0; + this._stepped = false; + this._stepTime = options["test-interval"] / 2; + }, { + + start: function(startTimestamp, stage) + { + Controller.prototype.start.call(this, startTimestamp, stage); + this._stepTime += startTimestamp; + }, + + tune: function(timestamp, stage) + { + if (this._stepped || timestamp < this._stepTime) + return; + + this.mark(Strings.json.samplingEndTimeOffset, timestamp); + this._stepped = true; + stage.tune(stage.complexity() * 3); + } +}); + +AdaptiveController = Utilities.createSubclass(Controller, + function(benchmark, options) + { + // Data series: timestamp, complexity, estimatedIntervalFrameLength + Controller.call(this, benchmark, options); + + // All tests start at 0, so we expect to see 60 fps quickly. + this._samplingTimestamp = options["test-interval"] / 2; + this._startedSampling = false; + this._targetFrameRate = options["frame-rate"]; + this._pid = new PIDController(this._targetFrameRate); + + this._intervalFrameCount = 0; + this._numberOfFramesToMeasurePerInterval = 4; + }, { + + start: function(startTimestamp, stage) + { + Controller.prototype.start.call(this, startTimestamp, stage); + + this._samplingTimestamp += startTimestamp; + this._intervalTimestamp = startTimestamp; + }, + + recordFirstSample: function(startTimestamp, stage) + { + this._sampler.record(startTimestamp, stage.complexity(), -1); + }, + + update: function(timestamp, stage) + { + if (!this._startedSampling && timestamp >= this._samplingTimestamp) { + this._startedSampling = true; + this.mark(Strings.json.samplingStartTimeOffset, this._samplingTimestamp); + } + + // Start the work for the next frame. + ++this._intervalFrameCount; + + if (this._intervalFrameCount < this._numberOfFramesToMeasurePerInterval) { + this._sampler.record(timestamp, stage.complexity(), -1); + return; + } + + // Adjust the test to reach the desired FPS. + var intervalLength = timestamp - this._intervalTimestamp; + this._frameLengthEstimator.sample(intervalLength / this._numberOfFramesToMeasurePerInterval); + var intervalEstimatedFrameRate = 1000 / this._frameLengthEstimator.estimate; + var tuneValue = -this._pid.tune(timestamp - this._startTimestamp, intervalLength, intervalEstimatedFrameRate); + tuneValue = tuneValue > 0 ? Math.floor(tuneValue) : Math.ceil(tuneValue); + stage.tune(tuneValue); + + this._sampler.record(timestamp, stage.complexity(), this._frameLengthEstimator.estimate); + + // Start the next interval. + this._intervalFrameCount = 0; + this._intervalTimestamp = timestamp; + } +}); + +RampController = Utilities.createSubclass(Controller, + function(benchmark, options) + { + // The tier warmup takes at most 5 seconds + options["sample-capacity"] = (options["test-interval"] / 1000 + 5) * 60; + Controller.call(this, benchmark, options); + + // Initially start with a tier test to find the bounds + // The number of objects in a tier test is 10^|_tier| + this._tier = -.5; + // The timestamp is first set after the first interval completes + this._tierStartTimestamp = 0; + this._minimumComplexity = 1; + this._maximumComplexity = 1; + + // After the tier range is determined, figure out the number of ramp iterations + var minimumRampLength = 3000; + var totalRampIterations = Math.max(1, Math.floor(this._endTimestamp / minimumRampLength)); + // Give a little extra room to run since the ramps won't be exactly this length + this._rampLength = Math.floor((this._endTimestamp - totalRampIterations * this.intervalSamplingLength) / totalRampIterations); + this._rampDidWarmup = false; + this._rampRegressions = []; + + this._finishedTierSampling = false; + this._changePointEstimator = new Experiment; + this._minimumComplexityEstimator = new Experiment; + // Estimates all frames within an interval + this._intervalFrameLengthEstimator = new Experiment; + }, { + + // If the engine can handle the tier's complexity at the desired frame rate, test for a short + // period, then move on to the next tier + tierFastTestLength: 250, + // If the engine is under stress, let the test run a little longer to let the measurement settle + tierSlowTestLength: 750, + + rampWarmupLength: 200, + + // Used for regression calculations in the ramps + frameLengthDesired: 1000/60, + // Add some tolerance; frame lengths shorter than this are considered to be @ the desired frame length + frameLengthDesiredThreshold: 1000/58, + // During tier sampling get at least this slow to find the right complexity range + frameLengthTierThreshold: 1000/30, + // Try to make each ramp get this slow so that we can cross the break point + frameLengthRampLowerThreshold: 1000/45, + // Do not let the regression calculation at the maximum complexity of a ramp get slower than this threshold + frameLengthRampUpperThreshold: 1000/20, + + start: function(startTimestamp, stage) + { + Controller.prototype.start.call(this, startTimestamp, stage); + this._rampStartTimestamp = 0; + this.intervalSamplingLength = 100; + }, + + didFinishInterval: function(timestamp, stage, intervalAverageFrameLength) + { + if (!this._finishedTierSampling) { + if (this._tierStartTimestamp > 0 && timestamp < this._tierStartTimestamp + this.tierFastTestLength) + return; + + var currentComplexity = stage.complexity(); + var currentFrameLength = this._frameLengthEstimator.estimate; + if (currentFrameLength < this.frameLengthTierThreshold) { + var isAnimatingAt60FPS = currentFrameLength < this.frameLengthDesiredThreshold; + var hasFinishedSlowTierTest = timestamp > this._tierStartTimestamp + this.tierSlowTestLength; + + if (!isAnimatingAt60FPS && !hasFinishedSlowTierTest) + return; + + // We're measuring at 60 fps, so quickly move on to the next tier, or + // we've slower than 60 fps, but we've let this tier run long enough to + // get an estimate + this._lastTierComplexity = currentComplexity; + this._lastTierFrameLength = currentFrameLength; + + this._tier += .5; + var nextTierComplexity = Math.round(Math.pow(10, this._tier)); + stage.tune(nextTierComplexity - currentComplexity); + + // Some tests may be unable to go beyond a certain capacity. If so, don't keep moving up tiers + if (stage.complexity() - currentComplexity > 0 || nextTierComplexity == 1) { + this._tierStartTimestamp = timestamp; + this.mark("Complexity: " + nextTierComplexity, timestamp); + return; + } + } else if (timestamp < this._tierStartTimestamp + this.tierSlowTestLength) + return; + + this._finishedTierSampling = true; + this.isFrameLengthEstimatorEnabled = false; + this.intervalSamplingLength = 120; + + // Extend the test length so that the full test length is made of the ramps + this._endTimestamp += timestamp; + this.mark(Strings.json.samplingStartTimeOffset, timestamp); + + this._minimumComplexity = 1; + this._possibleMinimumComplexity = this._minimumComplexity; + this._minimumComplexityEstimator.sample(this._minimumComplexity); + + // Sometimes this last tier will drop the frame length well below the threshold. + // Avoid going down that far since it means fewer measurements are taken in the 60 fps area. + // Interpolate a maximum complexity that gets us around the lowest threshold. + // Avoid doing this calculation if we never get out of the first tier (where this._lastTierComplexity is undefined). + if (this._lastTierComplexity && this._lastTierComplexity != currentComplexity) + this._maximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthTierThreshold, this._lastTierFrameLength, currentFrameLength), this._lastTierComplexity, currentComplexity)); + else { + // If the browser is capable of handling the most complex version of the test, use that + this._maximumComplexity = currentComplexity; + } + this._possibleMaximumComplexity = this._maximumComplexity; + + // If we get ourselves onto a ramp where the maximum complexity does not yield slow enough FPS, + // We'll use this as a boundary to find a higher maximum complexity for the next ramp + this._lastTierComplexity = currentComplexity; + this._lastTierFrameLength = currentFrameLength; + + // First ramp + stage.tune(this._maximumComplexity - currentComplexity); + this._rampDidWarmup = false; + // Start timestamp represents start of ramp iteration and warm up + this._rampStartTimestamp = timestamp; + return; + } + + if ((timestamp - this._rampStartTimestamp) < this.rampWarmupLength) + return; + + if (this._rampDidWarmup) + return; + + this._rampDidWarmup = true; + this._currentRampLength = this._rampStartTimestamp + this._rampLength - timestamp; + // Start timestamp represents start of ramp down, after warm up + this._rampStartTimestamp = timestamp; + this._rampStartIndex = this._sampler.sampleCount; + }, + + tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength) + { + if (!this._rampDidWarmup) + return; + + this._intervalFrameLengthEstimator.sample(lastFrameLength); + if (!didFinishInterval) + return; + + var currentComplexity = stage.complexity(); + var intervalFrameLengthMean = this._intervalFrameLengthEstimator.mean(); + var intervalFrameLengthStandardDeviation = this._intervalFrameLengthEstimator.standardDeviation(); + + if (intervalFrameLengthMean < this.frameLengthDesiredThreshold && this._intervalFrameLengthEstimator.cdf(this.frameLengthDesiredThreshold) > .9) { + this._possibleMinimumComplexity = Math.max(this._possibleMinimumComplexity, currentComplexity); + } else if (intervalFrameLengthStandardDeviation > 2) { + // In the case where we might have found a previous interval where 60fps was reached. We hit a significant blip, + // so we should resample this area in the next ramp. + this._possibleMinimumComplexity = 1; + } + if (intervalFrameLengthMean - intervalFrameLengthStandardDeviation > this.frameLengthRampLowerThreshold) + this._possibleMaximumComplexity = Math.min(this._possibleMaximumComplexity, currentComplexity); + this._intervalFrameLengthEstimator.reset(); + + var progress = (timestamp - this._rampStartTimestamp) / this._currentRampLength; + + if (progress < 1) { + // Reframe progress percentage so that the last interval of the ramp can sample at minimum complexity + progress = (timestamp - this._rampStartTimestamp) / (this._currentRampLength - this.intervalSamplingLength); + stage.tune(Math.max(this._minimumComplexity, Math.floor(Utilities.lerp(progress, this._maximumComplexity, this._minimumComplexity))) - currentComplexity); + return; + } + + var regression = new Regression(this._sampler.samples, this._getComplexity, this._getFrameLength, + this._sampler.sampleCount - 1, this._rampStartIndex, { desiredFrameLength: this.frameLengthDesired }); + this._rampRegressions.push(regression); + + var frameLengthAtMaxComplexity = regression.valueAt(this._maximumComplexity); + if (frameLengthAtMaxComplexity < this.frameLengthRampLowerThreshold) + this._possibleMaximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthRampLowerThreshold, frameLengthAtMaxComplexity, this._lastTierFrameLength), this._maximumComplexity, this._lastTierComplexity)); + // If the regression doesn't fit the first segment at all, keep the minimum bound at 1 + if ((timestamp - this._sampler.samples[0][this._sampler.sampleCount - regression.n1]) / this._currentRampLength < .25) + this._possibleMinimumComplexity = 1; + + this._minimumComplexityEstimator.sample(this._possibleMinimumComplexity); + this._minimumComplexity = Math.round(this._minimumComplexityEstimator.mean()); + + if (frameLengthAtMaxComplexity < this.frameLengthRampUpperThreshold) { + this._changePointEstimator.sample(regression.complexity); + // Ideally we'll target the change point in the middle of the ramp. If the range of the ramp is too small, there isn't enough + // range along the complexity (x) axis for a good regression calculation to be made, so force at least a range of 5 + // particles. Make it possible to increase the maximum complexity in case unexpected noise caps the regression too low. + this._maximumComplexity = Math.round(this._minimumComplexity + + Math.max(5, + this._possibleMaximumComplexity - this._minimumComplexity, + (this._changePointEstimator.mean() - this._minimumComplexity) * 2)); + } else { + // The slowest samples weighed the regression too heavily + this._maximumComplexity = Math.max(Math.round(.8 * this._maximumComplexity), this._minimumComplexity + 5); + } + + // Next ramp + stage.tune(this._maximumComplexity - stage.complexity()); + this._rampDidWarmup = false; + // Start timestamp represents start of ramp iteration and warm up + this._rampStartTimestamp = timestamp; + this._possibleMinimumComplexity = 1; + this._possibleMaximumComplexity = this._maximumComplexity; + }, + + _getComplexity: function(samples, i) { + return samples[1][i]; + }, + + _getFrameLength: function(samples, i) { + return samples[0][i] - samples[0][i - 1]; + }, + + processSamples: function(results) + { + Controller.prototype.processSamples.call(this, results); + + // Have samplingTimeOffset represent time 0 + var startTimestamp = this._marks[Strings.json.samplingStartTimeOffset].time; + + for (var markName in results[Strings.json.marks]) { + results[Strings.json.marks][markName].time -= startTimestamp; + } + + var controllerSamples = results[Strings.json.samples][Strings.json.controller]; + controllerSamples.forEach(function(timeSample) { + controllerSamples.setFieldInDatum(timeSample, Strings.json.time, controllerSamples.getFieldInDatum(timeSample, Strings.json.time) - startTimestamp); + }); + + // Aggregate all of the ramps into one big complexity-frameLength dataset + var complexitySamples = new SampleData(controllerSamples.fieldMap); + results[Strings.json.samples][Strings.json.complexity] = complexitySamples; + + results[Strings.json.controller] = []; + this._rampRegressions.forEach(function(ramp) { + var startIndex = ramp.startIndex, endIndex = ramp.endIndex; + var startTime = controllerSamples.getFieldInDatum(startIndex, Strings.json.time); + var endTime = controllerSamples.getFieldInDatum(endIndex, Strings.json.time); + var startComplexity = controllerSamples.getFieldInDatum(startIndex, Strings.json.complexity); + var endComplexity = controllerSamples.getFieldInDatum(endIndex, Strings.json.complexity); + + var regression = {}; + results[Strings.json.controller].push(regression); + + var percentage = (ramp.complexity - startComplexity) / (endComplexity - startComplexity); + var inflectionTime = startTime + percentage * (endTime - startTime); + + regression[Strings.json.regressions.segment1] = [ + [startTime, ramp.s2 + ramp.t2 * startComplexity], + [inflectionTime, ramp.s2 + ramp.t2 * ramp.complexity] + ]; + regression[Strings.json.regressions.segment2] = [ + [inflectionTime, ramp.s1 + ramp.t1 * ramp.complexity], + [endTime, ramp.s1 + ramp.t1 * endComplexity] + ]; + regression[Strings.json.complexity] = ramp.complexity; + regression[Strings.json.regressions.startIndex] = startIndex; + regression[Strings.json.regressions.endIndex] = endIndex; + regression[Strings.json.regressions.profile] = ramp.profile; + + for (var j = startIndex; j <= endIndex; ++j) + complexitySamples.push(controllerSamples.at(j)); + }); + + var complexityAverageSamples = new SampleData; + results[Strings.json.samples][Strings.json.complexityAverage] = complexityAverageSamples; + this._processComplexitySamples(complexitySamples, complexityAverageSamples); + } +}); + +Ramp30Controller = Utilities.createSubclass(RampController, + function(benchmark, options) + { + RampController.call(this, benchmark, options); + }, { + + frameLengthDesired: 1000/30, + frameLengthDesiredThreshold: 1000/29, + frameLengthTierThreshold: 1000/20, + frameLengthRampLowerThreshold: 1000/20, + frameLengthRampUpperThreshold: 1000/12 +}); + +Stage = Utilities.createClass( + function() + { + }, { + + initialize: function(benchmark) + { + this._benchmark = benchmark; + this._element = document.getElementById("stage"); + this._element.setAttribute("width", document.body.offsetWidth); + this._element.setAttribute("height", document.body.offsetHeight); + this._size = Point.elementClientSize(this._element).subtract(Insets.elementPadding(this._element).size); + }, + + get element() + { + return this._element; + }, + + get size() + { + return this._size; + }, + + complexity: function() + { + return 0; + }, + + tune: function() + { + throw "Not implemented"; + }, + + animate: function() + { + throw "Not implemented"; + }, + + clear: function() + { + return this.tune(-this.tune(0)); + } +}); + +Utilities.extendObject(Stage, { + random: function(min, max) + { + return (Pseudo.random() * (max - min)) + min; + }, + + randomBool: function() + { + return !!Math.round(Pseudo.random()); + }, + + randomSign: function() + { + return Pseudo.random() >= .5 ? 1 : -1; + }, + + randomInt: function(min, max) + { + return Math.floor(this.random(min, max + 1)); + }, + + randomPosition: function(maxPosition) + { + return new Point(this.randomInt(0, maxPosition.x), this.randomInt(0, maxPosition.y)); + }, + + randomSquareSize: function(min, max) + { + var side = this.random(min, max); + return new Point(side, side); + }, + + randomVelocity: function(maxVelocity) + { + return this.random(maxVelocity / 8, maxVelocity); + }, + + randomAngle: function() + { + return this.random(0, Math.PI * 2); + }, + + randomColor: function() + { + var min = 32; + var max = 256 - 32; + return "#" + + this.randomInt(min, max).toString(16) + + this.randomInt(min, max).toString(16) + + this.randomInt(min, max).toString(16); + }, + + randomStyleMixBlendMode: function() + { + var mixBlendModeList = [ + 'normal', + 'multiply', + 'screen', + 'overlay', + 'darken', + 'lighten', + 'color-dodge', + 'color-burn', + 'hard-light', + 'soft-light', + 'difference', + 'exclusion', + 'hue', + 'saturation', + 'color', + 'luminosity' + ]; + + return mixBlendModeList[this.randomInt(0, mixBlendModeList.length)]; + }, + + randomStyleFilter: function() + { + var filterList = [ + 'grayscale(50%)', + 'sepia(50%)', + 'saturate(50%)', + 'hue-rotate(180)', + 'invert(50%)', + 'opacity(50%)', + 'brightness(50%)', + 'contrast(50%)', + 'blur(10px)', + 'drop-shadow(10px 10px 10px gray)' + ]; + + return filterList[this.randomInt(0, filterList.length)]; + }, + + randomElementInArray: function(array) + { + return array[Stage.randomInt(0, array.length - 1)]; + }, + + rotatingColor: function(cycleLengthMs, saturation, lightness) + { + return "hsl(" + + Stage.dateFractionalValue(cycleLengthMs) * 360 + ", " + + ((saturation || .8) * 100).toFixed(0) + "%, " + + ((lightness || .35) * 100).toFixed(0) + "%)"; + }, + + // Returns a fractional value that wraps around within [0,1] + dateFractionalValue: function(cycleLengthMs) + { + return (Date.now() / (cycleLengthMs || 2000)) % 1; + }, + + // Returns an increasing value slowed down by factor + dateCounterValue: function(factor) + { + return Date.now() / factor; + }, + + randomRotater: function() + { + return new Rotater(this.random(1000, 10000)); + } +}); + +Rotater = Utilities.createClass( + function(rotateInterval) + { + this._timeDelta = 0; + this._rotateInterval = rotateInterval; + this._isSampling = false; + }, { + + get interval() + { + return this._rotateInterval; + }, + + next: function(timeDelta) + { + this._timeDelta = (this._timeDelta + timeDelta) % this._rotateInterval; + }, + + degree: function() + { + return (360 * this._timeDelta) / this._rotateInterval; + }, + + rotateZ: function() + { + return "rotateZ(" + Math.floor(this.degree()) + "deg)"; + }, + + rotate: function(center) + { + return "rotate(" + Math.floor(this.degree()) + ", " + center.x + "," + center.y + ")"; + } +}); + +Benchmark = Utilities.createClass( + function(stage, options) + { + this._animateLoop = this._animateLoop.bind(this); + + this._stage = stage; + this._stage.initialize(this, options); + + switch (options["time-measurement"]) + { + case "performance": + if (window.performance && window.performance.now) + this._getTimestamp = performance.now.bind(performance); + else + this._getTimestamp = null; + break; + case "raf": + this._getTimestamp = null; + break; + case "date": + this._getTimestamp = Date.now; + break; + } + + options["test-interval"] *= 1000; + switch (options["controller"]) + { + case "fixed": + this._controller = new FixedController(this, options); + break; + case "step": + this._controller = new StepController(this, options); + break; + case "adaptive": + this._controller = new AdaptiveController(this, options); + break; + case "ramp": + this._controller = new RampController(this, options); + break; + case "ramp30": + this._controller = new Ramp30Controller(this, options); + } + }, { + + get stage() + { + return this._stage; + }, + + get timestamp() + { + return this._currentTimestamp - this._startTimestamp; + }, + + backgroundColor: function() + { + var stage = window.getComputedStyle(document.getElementById("stage")); + return stage["background-color"]; + }, + + run: function() + { + return this.waitUntilReady().then(function() { + this._finishPromise = new SimplePromise; + this._previousTimestamp = undefined; + this._didWarmUp = false; + this._stage.tune(this._controller.initialComplexity - this._stage.complexity()); + this._animateLoop(); + return this._finishPromise; + }.bind(this)); + }, + + // Subclasses should override this if they have setup to do prior to commencing. + waitUntilReady: function() + { + var promise = new SimplePromise; + promise.resolve(); + return promise; + }, + + _animateLoop: function(timestamp) + { + timestamp = (this._getTimestamp && this._getTimestamp()) || timestamp; + this._currentTimestamp = timestamp; + + if (this._controller.shouldStop(timestamp)) { + this._finishPromise.resolve(this._controller.results()); + return; + } + + if (!this._didWarmUp) { + if (!this._previousTimestamp) + this._previousTimestamp = timestamp; + else if (timestamp - this._previousTimestamp >= 100) { + this._didWarmUp = true; + this._startTimestamp = timestamp; + this._controller.start(timestamp, this._stage); + this._previousTimestamp = timestamp; + } + + this._stage.animate(0); + requestAnimationFrame(this._animateLoop); + return; + } + + this._controller.update(timestamp, this._stage); + this._stage.animate(timestamp - this._previousTimestamp); + this._previousTimestamp = timestamp; + requestAnimationFrame(this._animateLoop); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js new file mode 100644 index 0000000000..9c2706e2a3 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js @@ -0,0 +1,268 @@ +SimpleKalmanEstimator = Utilities.createSubclass(Experiment, + function(processError, measurementError) { + Experiment.call(this, false); + var error = .5 * (Math.sqrt(processError * processError + 4 * processError * measurementError) - processError); + this._gain = error / (error + measurementError); + }, { + + sample: function(newMeasurement) + { + if (!this._initialized) { + this._initialized = true; + this.estimate = newMeasurement; + return; + } + + this.estimate = this.estimate + this._gain * (newMeasurement - this.estimate); + }, + + reset: function() + { + Experiment.prototype.reset.call(this); + this._initialized = false; + this.estimate = 0; + } +}); + +PIDController = Utilities.createClass( + function(ysp) + { + this._ysp = ysp; + this._out = 0; + + this._Kp = 0; + this._stage = PIDController.stages.WARMING; + + this._eold = 0; + this._I = 0; + }, { + + // Determines whether the current y is + // before ysp => (below ysp if ysp > y0) || (above ysp if ysp < y0) + // after ysp => (above ysp if ysp > y0) || (below ysp if ysp < y0) + _yPosition: function(y) + { + return (y < this._ysp) == (this._y0 < this._ysp) + ? PIDController.yPositions.BEFORE_SETPOINT + : PIDController.yPositions.AFTER_SETPOINT; + }, + + // Calculate the ultimate distance from y0 after time t. We want to move very + // slowly at the beginning to see how adding few items to the test can affect + // its output. The complexity of a single item might be big enough to keep the + // proportional gain very small but achieves the desired progress. But if y does + // not change significantly after adding few items, that means we need a much + // bigger gain. So we need to move over a cubic curve which increases very + // slowly with small t values but moves very fast with larger t values. + // The basic formula is: y = t^3 + // Change the formula to reach y=1 after 1000 ms: y = (t/1000)^3 + // Change the formula to reach y=(ysp - y0) after 1000 ms: y = (ysp - y0) * (t/1000)^3 + _distanceUltimate: function(t) + { + return (this._ysp - this._y0) * Math.pow(t / 1000, 3); + }, + + // Calculates the distance of y relative to y0. It also ensures we do not return + // zero by returning a epsilon value in the same direction as ultimate distance. + _distance: function(y, du) + { + const epsilon = 0.0001; + var d = y - this._y0; + return du < 0 ? Math.min(d, -epsilon) : Math.max(d, epsilon); + }, + + // Decides how much the proportional gain should be increased during the manual + // gain stage. We choose to use the ratio of the ultimate distance to the current + // distance as an indication of how much the system is responsive. We want + // to keep the increment under control so it does not cause the system instability + // So we choose to take the natural logarithm of this ratio. + _gainIncrement: function(t, y, e) + { + var du = this._distanceUltimate(t); + var d = this._distance(y, du); + return Math.log(du / d) * 0.1; + }, + + // Update the stage of the controller based on its current stage and the system output + _updateStage: function(y) + { + var yPosition = this._yPosition(y); + + switch (this._stage) { + case PIDController.stages.WARMING: + if (yPosition == PIDController.yPositions.AFTER_SETPOINT) + this._stage = PIDController.stages.OVERSHOOT; + break; + + case PIDController.stages.OVERSHOOT: + if (yPosition == PIDController.yPositions.BEFORE_SETPOINT) + this._stage = PIDController.stages.UNDERSHOOT; + break; + + case PIDController.stages.UNDERSHOOT: + if (yPosition == PIDController.yPositions.AFTER_SETPOINT) + this._stage = PIDController.stages.SATURATE; + break; + } + }, + + // Manual tuning is used before calculating the PID controller gains. + _tuneP: function(e) + { + // The output is the proportional term only. + return this._Kp * e; + }, + + // PID tuning function. Kp, Ti and Td were already calculated + _tunePID: function(h, y, e) + { + // Proportional term. + var P = this._Kp * e; + + // Integral term is the area under the curve starting from the beginning + // till the current time. + this._I += (this._Kp / this._Ti) * ((e + this._eold) / 2) * h; + + // Derivative term is the slope of the curve at the current time. + var D = (this._Kp * this._Td) * (e - this._eold) / h; + + // The ouput is a PID function. + return P + this._I + D; + }, + + // Apply different strategies for the tuning based on the stage of the controller. + _tune: function(t, h, y, e) + { + switch (this._stage) { + case PIDController.stages.WARMING: + // This is the first stage of the Zieglerâ€Nichols method. It increments + // the proportional gain till the system output passes the set-point value. + if (typeof this._y0 == "undefined") { + // This is the first time a tuning value is required. We want the test + // to add only one item. So we need to return -1 which forces us to + // choose the initial value of Kp to be = -1 / e + this._y0 = y; + this._Kp = -1 / e; + } else { + // Keep incrementing the Kp as long as we have not reached the + // set-point yet + this._Kp += this._gainIncrement(t, y, e); + } + + return this._tuneP(e); + + case PIDController.stages.OVERSHOOT: + // This is the second stage of the Zieglerâ€Nichols method. It measures the + // oscillation period. + if (typeof this._t0 == "undefined") { + // t is the time of the begining of the first overshot + this._t0 = t; + this._Kp /= 2; + } + + return this._tuneP(e); + + case PIDController.stages.UNDERSHOOT: + // This is the end of the Zieglerâ€Nichols method. We need to calculate the + // integral and derivative periods. + if (typeof this._Ti == "undefined") { + // t is the time of the end of the first overshot + var Tu = t - this._t0; + + // Calculate the system parameters from Kp and Tu assuming + // a "some overshoot" control type. See: + // https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method + this._Ti = Tu / 2; + this._Td = Tu / 3; + this._Kp = 0.33 * this._Kp; + + // Calculate the tracking time. + this._Tt = Math.sqrt(this._Ti * this._Td); + } + + return this._tunePID(h, y, e); + + case PIDController.stages.SATURATE: + return this._tunePID(h, y, e); + } + + return 0; + }, + + // Ensures the system does not fluctuates. + _saturate: function(v, e) + { + var u = v; + + switch (this._stage) { + case PIDController.stages.OVERSHOOT: + case PIDController.stages.UNDERSHOOT: + // Calculate the min-max values of the saturation actuator. + if (typeof this._min == "undefined") + this._min = this._max = this._out; + else { + this._min = Math.min(this._min, this._out); + this._max = Math.max(this._max, this._out); + } + break; + + case PIDController.stages.SATURATE: + const limitPercentage = 0.90; + var min = this._min > 0 ? Math.min(this._min, this._max * limitPercentage) : this._min; + var max = this._max < 0 ? Math.max(this._max, this._min * limitPercentage) : this._max; + var out = this._out + u; + + // Clip the controller output to the min-max values + out = Math.max(Math.min(max, out), min); + u = out - this._out; + + // Apply the back-calculation and tracking + if (u != v) + u += (this._Kp * this._Tt / this._Ti) * e; + break; + } + + this._out += u; + return u; + }, + + // Called from the benchmark to tune its test. It uses Ziegler-Nichols method + // to calculate the controller parameters. It then returns a PID tuning value. + tune: function(t, h, y) + { + this._updateStage(y); + + // Current error. + var e = this._ysp - y; + var v = this._tune(t, h, y, e); + + // Save e for the next call. + this._eold = e; + + // Apply back-calculation and tracking to avoid integrator windup + return this._saturate(v, e); + } +}); + +Utilities.extendObject(PIDController, { + // This enum will be used to tell whether the system output (or the controller input) + // is moving towards the set-point or away from it. + yPositions: { + BEFORE_SETPOINT: 0, + AFTER_SETPOINT: 1 + }, + + // The Ziegler-Nichols method for is used tuning the PID controller. The workflow of + // the tuning is split into four stages. The first two stages determine the values + // of the PID controller gains. During these two stages we return the proportional + // term only. The third stage is used to determine the min-max values of the + // saturation actuator. In the last stage back-calculation and tracking are applied + // to avoid integrator windup. During the last two stages, we return a PID control + // value. + stages: { + WARMING: 0, // Increase the value of the Kp until the system output reaches ysp. + OVERSHOOT: 1, // Measure the oscillation period and the overshoot value + UNDERSHOOT: 2, // Return PID value and measure the undershoot value + SATURATE: 3 // Return PID value and apply back-calculation and tracking. + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css new file mode 100644 index 0000000000..0b6ffdc4a2 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css @@ -0,0 +1,27 @@ +html { + height: 100%; +} +body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background-color: rgb(241, 241, 241); + font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif; +} + +#stage { + position: relative; + width: 100%; + height: 100%; + background-color: rgb(241, 241, 241); + overflow: hidden; +} + +#center-text { + position: absolute; + z-index: 3; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg new file mode 100644 index 0000000000..3c46ae0419 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png new file mode 100644 index 0000000000..3162f6ec00 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png differ diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg new file mode 100644 index 0000000000..4412626774 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js new file mode 100644 index 0000000000..cda985b221 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js @@ -0,0 +1,453 @@ +(function() { + +// === PAINT OBJECTS === + +CanvasLineSegment = Utilities.createClass( + function(stage) { + var radius = Stage.randomInt(10, 100); + var center = Stage.randomPosition(stage.size); + var delta = Point.pointOnCircle(Stage.randomAngle(), radius/2); + + this._point1 = center.add(delta); + this._point2 = center.subtract(delta); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 100); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.lineTo(this._point2.x, this._point2.y); + context.stroke(); + } +}); + +CanvasLinePoint = Utilities.createClass( + function(stage, coordinateMaximumFactor) { + var pointMaximum = new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y)); + this._point = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + }, { + + draw: function(context) { + context.lineTo(this._point.x, this._point.y); + } +}) + +CanvasQuadraticSegment = Utilities.createClass( + function(stage) { + var maxSize = Stage.randomInt(20, 200); + var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 50); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.quadraticCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y); + context.stroke(); + } +}); + +CanvasQuadraticPoint = Utilities.createClass( + function(stage, coordinateMaximumFactor) { + var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y))); + this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + }, { + + draw: function(context) { + context.quadraticCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y); + } +}); + +CanvasBezierSegment = Utilities.createClass( + function(stage) { + var maxSize = Stage.randomInt(20, 200); + var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point4 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 50); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._point4.x, this._point4.y); + context.stroke(); + } +}); + +CanvasBezierPoint = Utilities.createClass( + function(stage, coordinateMaximumFactor) { + var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y))); + this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + this._point3 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); + }, { + + draw: function(context) { + context.bezierCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y, this._point3.x, this._point3.y); + } +}); + +CanvasArcToSegment = Utilities.createClass( + function(stage) { + var maxSize = Stage.randomInt(20, 200); + var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._radius = Stage.randomInt(20, 200); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 50); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius); + context.stroke(); + } +}); + +CanvasArcToSegmentFill = Utilities.createClass( + function(stage) { + CanvasArcToSegment.call(this, stage); + }, { + + draw: function(context) { + context.fillStyle = this._color; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius); + context.fill(); + } +}); + +CanvasArcSegment = Utilities.createClass( + function(stage) { + var maxSize = Stage.randomInt(20, 200); + var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._radius = Stage.randomInt(20, 200); + this._startAngle = Stage.randomAngle(); + this._endAngle = Stage.randomAngle(); + this._counterclockwise = Stage.randomBool(); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 50); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); + context.stroke(); + } +}); + +CanvasArcSegmentFill = Utilities.createClass( + function(stage) { + CanvasArcSegment.call(this, stage); + }, { + + draw: function(context) { + context.fillStyle = this._color; + context.beginPath(); + context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); + context.fill(); + } +}); + +CanvasRect = Utilities.createClass( + function(stage) { + this._width = Stage.randomInt(20, 200); + this._height = Stage.randomInt(20, 200); + this._point = Stage.randomPosition(stage.size).subtract(new Point(this._width/2, this._height/2)); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 20); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.rect(this._point.x, this._point.y, this._width, this._height); + context.stroke(); + } +}); + +CanvasRectFill = Utilities.createClass( + function(stage) { + CanvasRect.call(this, stage); + }, { + + draw: function(context) { + context.fillStyle = this._color; + context.beginPath(); + context.rect(this._point.x, this._point.y, this._width, this._height); + context.fill(); + } +}); + +CanvasEllipse = Utilities.createClass( + function(stage) { + this._radius = new Point(Stage.randomInt(20, 200), Stage.randomInt(20, 200)); + var toCenter = Stage.randomPosition(stage.size).subtract(this._radius.multiply(.5)); + + this._center = Stage.randomPosition(this._radius).add(toCenter); + this._rotation = Stage.randomAngle(); + this._startAngle = Stage.randomAngle(); + this._endAngle = Stage.randomAngle(); + this._anticlockwise = Stage.randomBool(); + this._color = Stage.randomColor(); + this._lineWidth = Stage.randomInt(1, 20); + }, { + + draw: function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise); + context.stroke(); + } +}); + +CanvasEllipseFill = Utilities.createClass( + function(stage) { + CanvasEllipse.call(this, stage); + }, { + + draw: function(context) { + context.fillStyle = this._color; + context.beginPath(); + context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise); + context.fill(); + } +}); + +CanvasStroke = Utilities.createClass( + function (stage) { + this._object = new (Stage.randomElementInArray(this.objectTypes))(stage); + }, { + + objectTypes: [ + CanvasQuadraticSegment, + CanvasBezierSegment, + CanvasArcToSegment, + CanvasArcSegment, + CanvasRect, + CanvasEllipse + ], + + draw: function(context) { + this._object.draw(context); + } +}); + +CanvasFill = Utilities.createClass( + function (stage) { + this._object = new (Stage.randomElementInArray(this.objectTypes))(stage); + }, { + + objectTypes: [ + CanvasArcToSegmentFill, + CanvasArcSegmentFill, + CanvasRectFill, + CanvasEllipseFill + ], + + draw: function(context) { + this._object.draw(context); + } +}); + +// === STAGES === + +SimpleCanvasPathStrokeStage = Utilities.createSubclass(SimpleCanvasStage, + function(canvasObject) { + SimpleCanvasStage.call(this, canvasObject); + }, { + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + context.lineWidth = Stage.randomInt(1, 20); + context.strokeStyle = Stage.rotatingColor(); + context.beginPath(); + context.moveTo(this.size.x / 2, this.size.y / 2); + for (var i = 0, length = this.offsetIndex; i < length; ++i) + this.objects[i].draw(context); + context.stroke(); + } +}); + +SimpleCanvasPathFillStage = Utilities.createSubclass(SimpleCanvasStage, + function(canvasObject) { + SimpleCanvasStage.call(this, canvasObject); + }, { + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + context.fillStyle = Stage.rotatingColor(); + context.beginPath(); + context.moveTo(this.size.x / 2, this.size.y / 2); + for (var i = 0, length = this.offsetIndex; i < length; ++i) + this.objects[i].draw(context); + context.fill(); + } +}); + +CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage, + function() + { + SimpleCanvasStage.call(this, CanvasLineSegment); + }, { + + initialize: function(benchmark, options) + { + SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); + this.context.lineCap = options["lineCap"] || "butt"; + } +}); + +CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasPathStrokeStage, + function() + { + SimpleCanvasPathStrokeStage.call(this, CanvasLinePoint); + }, { + + initialize: function(benchmark, options) + { + SimpleCanvasPathStrokeStage.prototype.initialize.call(this, benchmark, options); + this.context.lineJoin = options["lineJoin"] || "bevel"; + } +}); + +CanvasLineDashStage = Utilities.createSubclass(SimpleCanvasStage, + function() + { + SimpleCanvasStage.call(this, CanvasLinePoint); + this._step = 0; + }, { + + initialize: function(benchmark, options) + { + SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); + this.context.setLineDash([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + this.context.lineWidth = 1; + this.context.strokeStyle = "#000"; + }, + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + context.lineDashOffset = this._step++; + context.beginPath(); + context.moveTo(this.size.x / 2, this.size.y / 2); + for (var i = 0, length = this.offsetIndex; i < length; ++i) + this.objects[i].draw(context); + context.stroke(); + } +}); + +// === BENCHMARK === + +CanvasPathBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + var stage; + switch (options["pathType"]) { + case "line": + stage = new CanvasLineSegmentStage(); + break; + case "linePath": { + if ("lineJoin" in options) + stage = new CanvasLinePathStage(); + if ("lineDash" in options) + stage = new CanvasLineDashStage(); + break; + } + case "quadratic": + stage = new SimpleCanvasStage(CanvasQuadraticSegment); + break; + case "quadraticPath": + stage = new SimpleCanvasPathStrokeStage(CanvasQuadraticPoint); + break; + case "bezier": + stage = new SimpleCanvasStage(CanvasBezierSegment); + break; + case "bezierPath": + stage = new SimpleCanvasPathStrokeStage(CanvasBezierPoint); + break; + case "arcTo": + stage = new SimpleCanvasStage(CanvasArcToSegment); + break; + case "arc": + stage = new SimpleCanvasStage(CanvasArcSegment); + break; + case "rect": + stage = new SimpleCanvasStage(CanvasRect); + break; + case "ellipse": + stage = new SimpleCanvasStage(CanvasEllipse); + break; + case "lineFill": + stage = new SimpleCanvasPathFillStage(CanvasLinePoint); + break; + case "quadraticFill": + stage = new SimpleCanvasPathFillStage(CanvasQuadraticPoint); + break; + case "bezierFill": + stage = new SimpleCanvasPathFillStage(CanvasBezierPoint); + break; + case "arcToFill": + stage = new SimpleCanvasStage(CanvasArcToSegmentFill); + break; + case "arcFill": + stage = new SimpleCanvasStage(CanvasArcSegmentFill); + break; + case "rectFill": + stage = new SimpleCanvasStage(CanvasRectFill); + break; + case "ellipseFill": + stage = new SimpleCanvasStage(CanvasEllipseFill); + break; + case "strokes": + stage = new SimpleCanvasStage(CanvasStroke); + break; + case "fills": + stage = new SimpleCanvasStage(CanvasFill); + break; + } + + Benchmark.call(this, stage, options); + } +); + +window.benchmarkClass = CanvasPathBenchmark; + +})(); \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js new file mode 100644 index 0000000000..483d535d75 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js @@ -0,0 +1,35 @@ +Utilities.extendObject(SimpleCanvasStage.prototype, { + tune: function(count) + { + if (count == 0) + return; + + if (count < 0) { + this.offsetIndex = Math.max(this.offsetIndex + count, 0); + return; + } + + this.offsetIndex = this.offsetIndex + count; + if (this.offsetIndex > this.objects.length) { + // For some tests, it may be easier to see how well the test is going + // by limiting the range of coordinates in which new objects can reside + var coordinateMaximumFactor = Math.min(this.objects.length, Math.min(this.size.x, this.size.y)) / Math.min(this.size.x, this.size.y); + var newIndex = this.offsetIndex - this.objects.length; + for (var i = 0; i < newIndex; ++i) + this.objects.push(new this._canvasObject(this, coordinateMaximumFactor)); + } + }, + + animate: function() + { + var context = this.context; + context.clearRect(0, 0, this.size.x, this.size.y); + for (var i = 0, length = this.offsetIndex; i < length; ++i) + this.objects[i].draw(context); + }, + + complexity: function() + { + return this.offsetIndex; + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js new file mode 100644 index 0000000000..f5d02b68a4 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js @@ -0,0 +1,119 @@ +(function() { + +CanvasImageTile = Utilities.createClass( + function(stage, source) + { + this._context = stage.context; + this._size = stage.tileSize; + this.source = source; + }, { + + getImageData: function() + { + this._imagedata = this._context.getImageData(this.source.x, this.source.y, this._size.width, this._size.height); + }, + + putImageData: function(destination) + { + this._context.putImageData(this._imagedata, destination.x, destination.y); + } +}); + +TiledCanvasImageStage = Utilities.createSubclass(Stage, + function(element, options) + { + Stage.call(this); + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + this.context = this.element.getContext("2d"); + this._setupTiles(); + }, + + _setupTiles: function() + { + const maxTilesPerRow = 50; + const maxTilesPerCol = 50; + + this.tileSize = this.size.multiply(new Point(1 / maxTilesPerRow, 1 / maxTilesPerCol)); + + this._tiles = new Array(maxTilesPerRow * maxTilesPerCol); + + var source = Point.zero; + for (var index = 0; index < this._tiles.length; ++index) { + this._tiles[index] = new CanvasImageTile(this, source); + source = this._nextTilePosition(source); + } + + this._ctiles = 0; + }, + + _nextTilePosition: function(destination) + { + var next = destination.add(this.tileSize); + + if (next.x >= this._size.width) + return new Point(0, next.y >= this._size.height ? 0 : next.y); + + return new Point(next.x, destination.y); + }, + + tune: function(count) + { + this._ctiles += count; + + this._ctiles = Math.max(this._ctiles, 0); + this._ctiles = Math.min(this._ctiles, this._tiles.length); + }, + + _drawBackground: function() + { + var size = this._benchmark._stage.size; + var gradient = this.context.createLinearGradient(0, 0, size.width, 0); + gradient.addColorStop(0, "red"); + gradient.addColorStop(1, "white"); + this.context.save(); + this.context.fillStyle = gradient; + this.context.fillRect(0, 0, size.width, size.height); + this.context.restore(); + }, + + animate: function(timeDelta) + { + this._drawBackground(); + + if (!this._ctiles) + return; + + this._tiles.shuffle(); + + var destinations = new Array(this._ctiles); + for (var index = 0; index < this._ctiles; ++index) { + this._tiles[index].getImageData(); + destinations[index] = this._tiles[index].source; + } + + destinations.shuffle(); + + for (var index = 0; index < this._ctiles; ++index) + this._tiles[index].putImageData(destinations[index]); + }, + + complexity: function() + { + return this._ctiles; + } +}); + +TiledCanvasImageBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new TiledCanvasImageStage(), options); + } +); + +window.benchmarkClass = TiledCanvasImageBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html new file mode 100644 index 0000000000..5bb69bc54f --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html new file mode 100644 index 0000000000..c7c0fef774 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js new file mode 100644 index 0000000000..b74984c010 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js @@ -0,0 +1,89 @@ +(function() { + +function TemplateCanvasObject(stage) +{ + // For the canvas stage, most likely you will need to create your + // animated object since it's only draw time thing. + + // Fill in your object data. +} + +TemplateCanvasObject.prototype = { + _draw: function() + { + // Draw your object. + }, + + animate: function(timeDelta) + { + // Redraw the animated object. The last time this animated + // item was drawn before 'timeDelta'. + + // Move your object. + + // Redraw your object. + this._draw(); + } +}; + +TemplateCanvasStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + this.context = this.element.getContext("2d"); + + // Define a collection for your objects. + }, + + tune: function(count) + { + // If count is -ve, -count elements need to be removed form the + // stage. If count is +ve, +count elements need to be added to + // the stage. + + // Change objects in the stage. + }, + + animate: function(timeDelta) + { + // Animate the elements such that all of them are redrawn. Most + // likely you will need to call TemplateCanvasObject.animate() + // for all your animated objects here. + + // Most likely you will need to clear the canvas with every redraw. + this.context.clearRect(0, 0, this.size.x, this.size.y); + + // Loop through all your objects and ask them to animate. + } +}); + +TemplateCanvasBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new TemplateCanvasStage(), options); + }, { + + // Override this function if the benchmark needs to wait for resources to be + // loaded. + // + // Default implementation returns a resolved promise, so that the benchmark + // benchmark starts right away. Here's an example where we're waiting 5 + // seconds before starting the benchmark. + waitUntilReady: function() + { + var promise = new SimplePromise; + window.setTimeout(function() { + promise.resolve(); + }, 5000); + return promise; + } +}); + +window.benchmarkClass = TemplateCanvasBenchmark; + +})(); \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js new file mode 100644 index 0000000000..cdaa814af0 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js @@ -0,0 +1,46 @@ +(function() { + +TemplateCssStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + + // Do initialization here. + }, + + tune: function(count) + { + // If count is -ve, -count elements need to be removed form the + // stage. If count is +ve, +count elements need to be added to + // the stage. + + // Change objects in the stage. + }, + + animate: function(timeDelta) + { + // Animate the elements such that all of them are redrawn. You + // may need to define your object so it keeps its animation data. + // This object should encapsulate a corrosponding HTMLElement. + // You may also define a method called animate() in this object + // and just call this function here for all the elements. + + // Loop through all your objects and ask them to animate. + } +}); + +TemplateCssBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new TemplateCssStage(), options); + } +); + +window.benchmarkClass = TemplateCssBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js new file mode 100644 index 0000000000..8fee9c3478 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js @@ -0,0 +1,46 @@ +(function() { + +TemplateSvgStage = Utilities.createSubclass(Stage, + function() + { + Stage.call(this); + }, { + + initialize: function(benchmark, options) + { + Stage.prototype.initialize.call(this, benchmark, options); + + // Do initialization here. + }, + + tune: function(count) + { + // If count is -ve, -count elements need to be removed form the + // stage. If count is +ve, +count elements need to be added to + // the stage. + + // TODO: Change objects in the stage. + }, + + animate: function(timeDelta) + { + // Animate the elements such that all of them are redrawn. You + // may need to define your object so it keeps its animation data. + // This object should encapsulate a corrosponding SVGElement. + // You may also define a method called animate() in this object + // and just call this function here for all the elements. + + // TODO: Loop through all your objects and ask them to animate. + } +}); + +TemplateSvgBenchmark = Utilities.createSubclass(Benchmark, + function(options) + { + Benchmark.call(this, new TemplateSvgStage(), options); + } +); + +window.benchmarkClass = TemplateSvgBenchmark; + +})(); diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html new file mode 100644 index 0000000000..dcb7f52861 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html new file mode 100644 index 0000000000..70eb214e95 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html @@ -0,0 +1,16 @@ + + + + + + + +
    + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html new file mode 100644 index 0000000000..7a14fc45d6 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/version b/third_party/webkit/PerformanceTests/MotionMark/version new file mode 100644 index 0000000000..241f47c42d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/version @@ -0,0 +1,2 @@ +1.0 +r205655+ \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/Speedometer/InteractiveRunner.html b/third_party/webkit/PerformanceTests/Speedometer/InteractiveRunner.html new file mode 100644 index 0000000000..9cbfaa2889 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/InteractiveRunner.html @@ -0,0 +1,173 @@ + + + +Speedometer 2.1 Interactive Runner + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/Speedometer/README_MOZILLA b/third_party/webkit/PerformanceTests/Speedometer/README_MOZILLA new file mode 100644 index 0000000000..de0cd8c204 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/README_MOZILLA @@ -0,0 +1,13 @@ +The source from this directory was copied from the +PerformanceTests/Speedometer directory of the Webkit repository +at: https://svn.webkit.org/repository/webkit/trunk/PerformanceTests/Speedometer2.1/ + +The SVN revision used was: 294153 + +The contents of this directory are intended for use to "train" the +profile guided optimization (PGO) of Firefox and for benchmarking +scenarios. The files inside this directory are not intended to ship +with Firefox or any other product. If files inside this directory +are useful for other purposes (e.g. JavaScript libraries), consumers +should vendor those files separately, as it is not appropriate to pull +in components of Speedometer for use outside of Speedometer. diff --git a/third_party/webkit/PerformanceTests/Speedometer/index.html b/third_party/webkit/PerformanceTests/Speedometer/index.html new file mode 100644 index 0000000000..acac49d0f0 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/index.html @@ -0,0 +1,107 @@ + + + + + Speedometer 2.1 + + + + + + + + +
    + + +
    +

    + Speedometer is a browser benchmark that measures the responsiveness of Web applications. + It uses demo web applications to simulate user actions such as adding to-do items. +

    +

    + Your browser window is too small. For most accurate results, please make the view port size at least 850px by 650px.
    + It's currently . +

    +
    + +
    +

    About Speedometer

    +
    + +
    +
    +
    +
    +
    + +
    +

    Runs / Minute

    +
    +
    +
    +
    +
    + + +
    +
    + +
    +

    Detailed Results

    +
    +
    +
    +
    + + +
    +

    About Speedometer

    +
    + +
    +

    About Speedometer 2.1

    + +

    Speedometer tests a browser's Web app responsiveness by timing simulated user interactions.

    + +

    + This benchmark simulates user actions for adding, completing, and removing to-do items using multiple examples in TodoMVC. + Each example in TodoMVC implements the same todo application using DOM APIs in different ways. + Some call DOM APIs directly from ECMAScript 5 (ES5), ECMASCript 2015 (ES6), ES6 transpiled to ES5, and Elm transpiled to ES5. + Others use one of eleven popular JavaScript frameworks: React, React with Redux, Ember.js, Backbone.js, + AngularJS, (new) Angular, Vue.js, jQuery, Preact, Inferno, and Flight. + + Many of these frameworks are used on the most popular websites in the world, such as Facebook and Twitter. + The performance of these types of operations depends on the speed of the DOM APIs, the JavaScript engine, + CSS style resolution, layout, and other technologies. +

    + +

    + Although user-driven actions like mouse movements and keyboard input cannot be accurately emulated in JavaScript, + Speedometer does its best to faithfully replay a typical workload within the demo applications. + To make the run time long enough to measure with the limited precision, + we synchronously execute a large number of the operations, such as adding one hundred to-do items. +

    + +

    + Modern browser engines execute some work asynchronously as an optimization strategy to reduce the run time of synchronous operations. + While returning control back to JavaScript execution as soon as possible is worth pursuing, + the run time cost of such an asynchronous work should still be taken into a holistic measurement of web application performance. + In addition, some modern JavaScript frameworks such as Vue.js and Preact call into DOM APIs asynchronously as an optimization technique. + Speedometer approximates the run time of this asynchronous work in the UI thread with a zero-second timer + that is scheduled immediately after each execution of synchronous operations. +

    + +

    + Speedometer does not attempt to measure concurrent asynchronous work that does not directly impact the UI thread, + which tends not to affect app responsiveness. +

    + +

    + Note: Speedometer should not be used as a way to compare the performance of different JavaScript frameworks + as work load differs greatly in each framework. +

    +
    +
    + + diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-report.js b/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-report.js new file mode 100644 index 0000000000..972fbb0529 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-report.js @@ -0,0 +1,105 @@ +// This file can be customized to report results as needed. + +(function () { + if ((!window.testRunner && location.search != '?webkit' && location.hash != '#webkit') + && location.search != '?gecko' && location.search != '?raptor') + return; + + if (window.testRunner) + testRunner.waitUntilDone(); + + var scriptElement = document.createElement('script'); + scriptElement.src = '../resources/runner.js'; + document.head.appendChild(scriptElement); + + var styleElement = document.createElement('style'); + styleElement.textContent = 'pre { padding-top: 600px; }'; + document.head.appendChild(styleElement); + + var createTest; + var valuesByIteration = new Array; + + window.onload = function () { + document.body.removeChild(document.querySelector('main')); + startBenchmark(); + } + + window.benchmarkClient = { + iterationCount: 5, // Use 4 different instances of DRT/WTR to run 5 iterations. + willStartFirstIteration: function (iterationCount) { + createTest = function (name, aggregator, isLastTest) { + return { + customIterationCount: iterationCount, + doNotIgnoreInitialRun: true, + doNotMeasureMemoryUsage: true, + continueTesting: !isLastTest, + unit: 'ms', + name: name, + aggregator: aggregator}; + } + if (window.PerfTestRunner) { + PerfTestRunner.prepareToMeasureValuesAsync(createTest(null, 'Total')); + } + }, + didRunSuites: function (measuredValues) { + if (window.PerfTestRunner) + PerfTestRunner.measureValueAsync(measuredValues.total); + valuesByIteration.push(measuredValues.tests); + }, + didFinishLastIteration: function () { + document.head.removeChild(document.querySelector('style')); + + var measuredValuesByFullName = {}; + function addToMeasuredValue(value, fullName, aggregator) { + var values = measuredValuesByFullName[fullName] || new Array; + measuredValuesByFullName[fullName] = values; + values.push(value); + values.aggregator = aggregator; + } + + valuesByIteration.forEach(function (measuredValues) { + for (var suiteName in measuredValues) { + var suite = measuredValues[suiteName]; + for (var testName in suite.tests) { + var test = suite.tests[testName]; + for (var subtestName in test.tests) + addToMeasuredValue(test.tests[subtestName], suiteName + '/' + testName + '/' + subtestName); + addToMeasuredValue(test.total, suiteName + '/' + testName, 'Total'); + } + addToMeasuredValue(suite.total, suiteName, 'Total'); + } + }); + + var fullNames = new Array; + for (var fullName in measuredValuesByFullName) { + fullNames.push(fullName); + } + + if (typeof tpRecordTime !== "undefined" || location.search == '?raptor') { + var values = new Array; + var allNames = new Array; + for (var i = 0; i < fullNames.length; i++) { + vals = measuredValuesByFullName[fullNames[i]]; + values.push(vals); + for (var count=0; count < vals.length; count ++) { + allNames.push(fullNames[i]); + } + } + + if (location.search == '?raptor') { + _data = ['raptor-benchmark', 'speedometer', measuredValuesByFullName]; + console.log('speedometer source about to post results to the raptor webext'); + window.postMessage(_data, '*'); + window.sessionStorage.setItem('benchmark_results', JSON.stringify(_data)); + } else { + tpRecordTime(values.join(','), 0, allNames.join(',')); + } + } else { + for (var i = 0; i < fullNames.length; i++) { + var values = measuredValuesByFullName[fullNames[i]]; + PerfTestRunner.reportValues(createTest(fullNames[i], values.aggregator, i + 1 == fullNames.length), values); + } + } + } + }; +})(); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-runner.js b/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-runner.js new file mode 100644 index 0000000000..751992b4f1 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/benchmark-runner.js @@ -0,0 +1,305 @@ +// FIXME: Use the real promise if available. +// FIXME: Make sure this interface is compatible with the real Promise. +function SimplePromise() { + this._chainedPromise = null; + this._callback = null; +} + +SimplePromise.prototype.then = function (callback) { + if (this._callback) + throw "SimplePromise doesn't support multiple calls to then"; + this._callback = callback; + this._chainedPromise = new SimplePromise; + + if (this._resolved) + this.resolve(this._resolvedValue); + + return this._chainedPromise; +} + +SimplePromise.prototype.resolve = function (value) { + if (!this._callback) { + this._resolved = true; + this._resolvedValue = value; + return; + } + + var result = this._callback(value); + if (result instanceof SimplePromise) { + var chainedPromise = this._chainedPromise; + result.then(function (result) { chainedPromise.resolve(result); }); + } else + this._chainedPromise.resolve(result); +} + +function BenchmarkTestStep(testName, testFunction) { + this.name = testName; + this.run = testFunction; +} + +function BenchmarkRunner(suites, client) { + this._suites = suites; + this._prepareReturnValue = null; + this._client = client; +} + +BenchmarkRunner.prototype.waitForElement = function (selector) { + var promise = new SimplePromise; + var contentDocument = this._frame.contentDocument; + + function resolveIfReady() { + var element = contentDocument.querySelector(selector); + if (element) { + window.requestAnimationFrame(function () { + return promise.resolve(element); + }); + return; + } + setTimeout(resolveIfReady, 50); + } + + resolveIfReady(); + return promise; +} + +BenchmarkRunner.prototype._removeFrame = function () { + if (this._frame) { + this._frame.parentNode.removeChild(this._frame); + this._frame = null; + } +} + +BenchmarkRunner.prototype._appendFrame = function (src) { + var frame = document.createElement('iframe'); + frame.style.width = '800px'; + frame.style.height = '600px'; + frame.style.border = '0px none'; + frame.style.position = 'absolute'; + frame.setAttribute('scrolling', 'no'); + + var marginLeft = parseInt(getComputedStyle(document.body).marginLeft); + var marginTop = parseInt(getComputedStyle(document.body).marginTop); + if (window.innerWidth > 800 + marginLeft && window.innerHeight > 600 + marginTop) { + frame.style.left = marginLeft + 'px'; + frame.style.top = marginTop + 'px'; + } else { + frame.style.left = '0px'; + frame.style.top = '0px'; + } + + if (this._client && this._client.willAddTestFrame) + this._client.willAddTestFrame(frame); + + document.body.insertBefore(frame, document.body.firstChild); + this._frame = frame; + return frame; +} + +BenchmarkRunner.prototype._waitAndWarmUp = function () { + var startTime = Date.now(); + + function Fibonacci(n) { + if (Date.now() - startTime > 100) + return; + if (n <= 0) + return 0; + else if (n == 1) + return 1; + return Fibonacci(n - 2) + Fibonacci(n - 1); + } + + var promise = new SimplePromise; + setTimeout(function () { + Fibonacci(100); + promise.resolve(); + }, 200); + return promise; +} + +BenchmarkRunner.prototype._writeMark = function(name) { + if (window.performance && window.performance.mark) + window.performance.mark(name); +} + +// This function ought be as simple as possible. Don't even use SimplePromise. +BenchmarkRunner.prototype._runTest = function(suite, test, prepareReturnValue, callback) +{ + var self = this; + var now = window.performance && window.performance.now ? function () { return window.performance.now(); } : Date.now; + + var contentWindow = self._frame.contentWindow; + var contentDocument = self._frame.contentDocument; + + self._writeMark(suite.name + '.' + test.name + '-start'); + var startTime = now(); + test.run(prepareReturnValue, contentWindow, contentDocument); + var endTime = now(); + self._writeMark(suite.name + '.' + test.name + '-sync-end'); + + var syncTime = endTime - startTime; + + var startTime = now(); + setTimeout(function () { + // Some browsers don't immediately update the layout for paint. + // Force the layout here to ensure we're measuring the layout time. + var height = self._frame.contentDocument.body.getBoundingClientRect().height; + var endTime = now(); + self._frame.contentWindow._unusedHeightValue = height; // Prevent dead code elimination. + self._writeMark(suite.name + '.' + test.name + '-async-end'); + window.requestAnimationFrame(function () { + callback(syncTime, endTime - startTime, height); + }); + }, 0); +} + +function BenchmarkState(suites) { + this._suites = suites; + this._suiteIndex = -1; + this._testIndex = 0; + this.next(); +} + +BenchmarkState.prototype.currentSuite = function() { + return this._suites[this._suiteIndex]; +} + +BenchmarkState.prototype.currentTest = function () { + var suite = this.currentSuite(); + return suite ? suite.tests[this._testIndex] : null; +} + +BenchmarkState.prototype.next = function () { + this._testIndex++; + + var suite = this._suites[this._suiteIndex]; + if (suite && this._testIndex < suite.tests.length) + return this; + + this._testIndex = 0; + do { + this._suiteIndex++; + } while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled); + + return this; +} + +BenchmarkState.prototype.isFirstTest = function () { + return !this._testIndex; +} + +BenchmarkState.prototype.prepareCurrentSuite = function (runner, frame) { + var suite = this.currentSuite(); + var promise = new SimplePromise; + frame.onload = function () { + suite.prepare(runner, frame.contentWindow, frame.contentDocument).then(function (result) { promise.resolve(result); }); + } + frame.src = 'resources/' + suite.url; + return promise; +} + +BenchmarkRunner.prototype.step = function (state) { + if (!state) { + state = new BenchmarkState(this._suites); + this._measuredValues = {tests: {}, total: 0, mean: NaN, geomean: NaN, score: NaN}; + } + + var suite = state.currentSuite(); + if (!suite) { + this._finalize(); + var promise = new SimplePromise; + promise.resolve(); + return promise; + } + + if (state.isFirstTest()) { + this._removeFrame(); + var self = this; + return state.prepareCurrentSuite(this, this._appendFrame()).then(function (prepareReturnValue) { + self._prepareReturnValue = prepareReturnValue; + return self._runTestAndRecordResults(state); + }); + } + + return this._runTestAndRecordResults(state); +} + +BenchmarkRunner.prototype.runAllSteps = function (startingState) { + var nextCallee = this.runAllSteps.bind(this); + this.step(startingState).then(function (nextState) { + if (nextState) + nextCallee(nextState); + }); +} + +BenchmarkRunner.prototype.runMultipleIterations = function (iterationCount) { + var self = this; + var currentIteration = 0; + + this._runNextIteration = function () { + currentIteration++; + if (currentIteration < iterationCount) + self.runAllSteps(); + else if (this._client && this._client.didFinishLastIteration) + this._client.didFinishLastIteration(); + } + + if (this._client && this._client.willStartFirstIteration) + this._client.willStartFirstIteration(iterationCount); + + self.runAllSteps(); +} + +BenchmarkRunner.prototype._runTestAndRecordResults = function (state) { + var promise = new SimplePromise; + var suite = state.currentSuite(); + var test = state.currentTest(); + + if (this._client && this._client.willRunTest) + this._client.willRunTest(suite, test); + + var self = this; + setTimeout(function () { + self._runTest(suite, test, self._prepareReturnValue, function (syncTime, asyncTime) { + var suiteResults = self._measuredValues.tests[suite.name] || {tests:{}, total: 0}; + var total = syncTime + asyncTime; + self._measuredValues.tests[suite.name] = suiteResults; + suiteResults.tests[test.name] = {tests: {'Sync': syncTime, 'Async': asyncTime}, total: total}; + suiteResults.total += total; + + if (self._client && self._client.didRunTest) + self._client.didRunTest(suite, test); + + state.next(); + promise.resolve(state); + }); + }, 0); + return promise; +} + +BenchmarkRunner.prototype._finalize = function () { + this._removeFrame(); + + if (this._client && this._client.didRunSuites) { + var product = 1; + var values = []; + for (var suiteName in this._measuredValues.tests) { + var suiteTotal = this._measuredValues.tests[suiteName].total; + product *= suiteTotal; + values.push(suiteTotal); + } + + values.sort(function (a, b) { return a - b }); // Avoid the loss of significance for the sum. + var total = values.reduce(function (a, b) { return a + b }); + var geomean = Math.pow(product, 1 / values.length); + + var correctionFactor = 3; // This factor makes the test score look reasonably fit within 0 to 140. + this._measuredValues.total = total; + this._measuredValues.mean = total / values.length; + this._measuredValues.geomean = geomean; + this._measuredValues.score = 60 * 1000 / geomean / correctionFactor; + this._client.didRunSuites(this._measuredValues); + } + + if (this._runNextIteration) + this._runNextIteration(); +} diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/LICENSE.md b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/LICENSE.md new file mode 100644 index 0000000000..631a81ed8c --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) Twitter Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/README.md b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/README.md new file mode 100644 index 0000000000..901be3df39 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/README.md @@ -0,0 +1,5 @@ +# Flight example app + +[![Build Status](https://travis-ci.org/flightjs/example-app.png?branch=master)](http://travis-ci.org/flightjs/example-app) + +An example Flight application. diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/boot/page.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/boot/page.js new file mode 100644 index 0000000000..f561f8e2c6 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/boot/page.js @@ -0,0 +1,47 @@ +'use strict'; + +define( + + [ + 'app/component_data/mail_items', + 'app/component_data/compose_box', + 'app/component_data/move_to', + 'app/component_ui/mail_items', + 'app/component_ui/mail_controls', + 'app/component_ui/compose_box', + 'app/component_ui/folders', + 'app/component_ui/move_to_selector' + ], + + function( + MailItemsData, + ComposeBoxData, + MoveToData, + MailItemsUI, + MailControlsUI, + ComposeBoxUI, + FoldersUI, + MoveToSelectorUI) { + + function initialize() { + MailItemsData.attachTo(document); + ComposeBoxData.attachTo(document, { + selectedFolders: ['inbox'] + }); + MoveToData.attachTo(document); + MailItemsUI.attachTo('#mail_items', { + itemContainerSelector: '#mail_items_TB', + selectedFolders: ['inbox'] + }); + MailControlsUI.attachTo('#mail_controls'); + ComposeBoxUI.attachTo('#compose_box'); + FoldersUI.attachTo('#folders'); + MoveToSelectorUI.attachTo('#move_to_selector', { + moveActionSelector: '#move_mail', + selectedFolders: ['inbox'] + }); + } + + return initialize; + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/compose_box.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/compose_box.js new file mode 100644 index 0000000000..e728086f02 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/compose_box.js @@ -0,0 +1,93 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + 'components/mustache/mustache', + 'app/data', + 'app/templates' + ], + + function(defineComponent, Mustache, dataStore, templates) { + return defineComponent(composeBox); + + function composeBox() { + + this.defaultAttrs({ + dataStore: dataStore, + recipientHintId: 'recipient_hint', + subjectHint: 'Subject', + messageHint: 'Message', + toHint: 'To', + forwardPrefix: 'Fw', + replyPrefix: 'Re' + }); + + this.serveComposeBox = function(ev, data) { + this.trigger("dataComposeBoxServed", { + markup: this.renderComposeBox(data.type, data.relatedMailId), + type: data.type}); + }; + + this.getSubject = function(type, relatedMailId) { + var relatedMail = this.attr.dataStore.mail.filter(function(each) { + return each.id == relatedMailId; + })[0]; + + var subject = relatedMail && relatedMail.subject; + + var subjectLookup = { + newMail: this.attr.subjectHint, + forward: this.attr.forwardPrefix + ": " + subject, + reply: this.attr.replyPrefix + ": " + subject + } + + return subjectLookup[type]; + }; + + this.renderComposeBox = function(type, relatedMailId) { + var recipientId = this.getRecipientId(type, relatedMailId); + var contacts = this.attr.dataStore.contacts.map(function(contact) { + contact.recipient = (contact.id == recipientId); + return contact; + }); + + return Mustache.render(templates.composeBox, { + newMail: type == 'newMail', + reply: type == 'reply', + subject: this.getSubject(type, relatedMailId), + message: this.attr.messageHint, + contacts: contacts + }); + }; + + this.getRecipientId = function(type, relatedMailId) { + var relatedMail = (type == 'reply') && this.attr.dataStore.mail.filter(function(each) { + return each.id == relatedMailId; + })[0]; + + return relatedMail && relatedMail.contact_id || this.attr.recipientHintId; + }; + + + this.send = function(ev, data) { + this.attr.dataStore.mail.push({ + id: String(Date.now()), + contact_id: data.to_id, + folders: ["sent"], + time: Date.now(), + subject: data.subject, + message: data.message + }); + this.trigger('dataMailItemsRefreshRequested', {folder: data.currentFolder}); + }; + + this.after("initialize", function() { + this.on("uiComposeBoxRequested", this.serveComposeBox); + this.on("uiSendRequested", this.send); + }); + } + + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/mail_items.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/mail_items.js new file mode 100644 index 0000000000..380ff9a0e8 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/mail_items.js @@ -0,0 +1,68 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + 'components/mustache/mustache', + 'app/data', + 'app/templates' + ], + + function(defineComponent, Mustache, dataStore, templates) { + return defineComponent(mailItems); + + function mailItems() { + + this.defaultAttrs({ + folder: 'inbox', + dataStore: dataStore + }); + + this.serveMailItems = function(ev, data) { + var folder = (data && data.folder) || this.attr.folder; + this.trigger("dataMailItemsServed", {markup: this.renderItems(this.assembleItems(folder))}) + }; + + this.renderItems = function(items) { + return Mustache.render(templates.mailItem, {mailItems: items}); + }; + + this.assembleItems = function(folder) { + var items = []; + + this.attr.dataStore.mail.forEach(function(each) { + if (each.folders && each.folders.indexOf(folder) > -1) { + items.push(this.getItemForView(each)); + } + }, this); + + return items; + }; + + this.getItemForView = function(itemData) { + var thisItem, thisContact, msg + + thisItem = {id: itemData.id, important: itemData.important}; + + thisContact = this.attr.dataStore.contacts.filter(function(contact) { + return contact.id == itemData.contact_id + })[0]; + thisItem.name = [thisContact.firstName, thisContact.lastName].join(' '); + + var subj = itemData.subject; + thisItem.formattedSubject = subj.length > 70 ? subj.slice(0, 70) + "..." : subj; + + var msg = itemData.message; + thisItem.formattedMessage = msg.length > 70 ? msg.slice(0, 70) + "..." : msg; + + return thisItem; + }; + + this.after("initialize", function() { + this.on("uiMailItemsRequested", this.serveMailItems); + this.on("dataMailItemsRefreshRequested", this.serveMailItems); + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/move_to.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/move_to.js new file mode 100644 index 0000000000..46f248540b --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_data/move_to.js @@ -0,0 +1,52 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + 'components/mustache/mustache', + 'app/data', + 'app/templates' + ], + + function(defineComponent, Mustache, dataStore, templates) { + return defineComponent(moveTo); + + function moveTo() { + + this.defaultAttrs({ + dataStore: dataStore + }); + + this.serveAvailableFolders = function(ev, data) { + this.trigger("dataMoveToItemsServed", { + markup: this.renderFolderSelector(this.getOtherFolders(data.folder)) + }) + }; + + this.renderFolderSelector = function(items) { + return Mustache.render(templates.moveToSelector, {moveToItems: items}); + }; + + this.moveItems = function(ev, data) { + var itemsToMoveIds = data.itemIds + this.attr.dataStore.mail.forEach(function(item) { + if (itemsToMoveIds.indexOf(item.id) > -1) { + item.folders = [data.toFolder]; + } + }); + this.trigger('dataMailItemsRefreshRequested', {folder: data.fromFolder}); + }; + + this.getOtherFolders = function(folder) { + return this.attr.dataStore.folders.filter(function(e) {return e != folder}); + }; + + this.after("initialize", function() { + this.on("uiAvailableFoldersRequested", this.serveAvailableFolders); + this.on("uiMoveItemsRequested", this.moveItems); + }); + } + + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/compose_box.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/compose_box.js new file mode 100644 index 0000000000..feb14040be --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/compose_box.js @@ -0,0 +1,113 @@ +'use strict'; + +define( + + [ + 'flight/lib/component' + ], + + function(defineComponent) { + + return defineComponent(composeBox); + + function composeBox() { + + this.defaultAttrs({ + newMailType: 'newMail', + forwardMailType: 'forward', + replyMailType: 'reply', + hintClass: 'hint', + selectedFolders: [], + selectedMailItems: [], + + //selectors + composeControl: '.compose', + newControlSelector: '#new_mail', + cancelSelector: '#cancel_composed', + sendSelector: '#send_composed', + toSelector: '#compose_to', + subjectSelector: '#compose_subject', + messageSelector: '#compose_message', + recipientSelector: '#recipient_select', + recipientHintSelector: '#recipient_hint', + selectedRecipientSelector: '#recipient_select :selected', + hintSelector: 'div.hint' + }); + + this.newMail = function() { + this.requestComposeBox(this.attr.newMailType); + }; + + this.forward = function() { + this.requestComposeBox(this.attr.forwardMailType, this.attr.selectedMailItems); + }; + + this.reply = function() { + this.requestComposeBox(this.attr.replyMailType, this.attr.selectedMailItems); + }; + + this.requestComposeBox = function(type, relatedMailId) { + this.trigger('uiComposeBoxRequested', {type: type, relatedMailId: relatedMailId}); + }; + + this.launchComposeBox = function(ev, data) { + var focusSelector = (data.type == this.attr.replyMailType) ? 'messageSelector' : 'toSelector'; + this.$node.html(data.markup).show(); + this.select(focusSelector).focus(); + }; + + this.cancel = function() { + this.$node.html('').hide(); + }; + + this.requestSend = function() { + var data = { + to_id: this.select('selectedRecipientSelector').attr('id'), + subject: this.select('subjectSelector').text(), + message: this.select('messageSelector').text(), + currentFolder: this.attr.selectedFolders[0] + }; + this.trigger('uiSendRequested', data); + this.$node.hide(); + }; + + this.enableSend = function() { + this.select('recipientHintSelector').attr('disabled', 'disabled'); + this.select('sendSelector').removeAttr('disabled'); + }; + + this.removeHint = function(ev, data) { + $(ev.target).html('').removeClass(this.attr.hintClass); + }; + + this.updateMailItemSelections = function(ev, data) { + this.attr.selectedMailItems = data.selectedIds; + } + + this.updateFolderSelections = function(ev, data) { + this.attr.selectedFolders = data.selectedIds; + } + + this.after('initialize', function() { + this.on(document, 'dataComposeBoxServed', this.launchComposeBox); + this.on(document, 'uiForwardMail', this.forward); + this.on(document, 'uiReplyToMail', this.reply); + this.on(document, 'uiMailItemSelectionChanged', this.updateMailItemSelections); + this.on(document, 'uiFolderSelectionChanged', this.updateFolderSelections); + + //the following bindings use delegation so that the event target is read at event time + this.on(document, "click", { + 'cancelSelector': this.cancel, + 'sendSelector': this.requestSend, + 'newControlSelector': this.newMail + }); + this.on('change', { + 'recipientSelector': this.enableSend + }); + this.on('keydown', { + 'hintSelector': this.removeHint + }); + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/folders.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/folders.js new file mode 100644 index 0000000000..f8504939eb --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/folders.js @@ -0,0 +1,34 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + './with_select' + ], + + function(defineComponent, withSelect) { + + return defineComponent(folders, withSelect); + + function folders() { + + this.defaultAttrs({ + selectedClass: 'selected', + selectionChangedEvent: 'uiFolderSelectionChanged', + + //selectors + itemSelector: 'li.folder-item', + selectedItemSelector: 'li.folder-item.selected' + }); + + this.fetchMailItems = function(ev, data) { + this.trigger('uiMailItemsRequested', {folder: data.selectedIds[0]}); + } + + this.after('initialize', function() { + this.on('uiFolderSelectionChanged', this.fetchMailItems); + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_controls.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_controls.js new file mode 100644 index 0000000000..959f554502 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_controls.js @@ -0,0 +1,67 @@ +'use strict'; + +define( + [ + 'flight/lib/component' + ], + + function(defineComponent) { + + return defineComponent(mailControls); + + function mailControls() { + this.defaultAttrs({ + //selectors + actionControlsSelector: 'button.mail-action', + deleteControlSelector: '#delete_mail', + moveControlSelector: '#move_mail', + forwardControlSelector: '#forward', + replyControlSelector: '#reply', + singleItemActionSelector: 'button.single-item' + }); + + this.disableAll = function() { + this.select('actionControlsSelector').attr('disabled', 'disabled'); + }; + + this.restyleOnSelectionChange = function(ev, data) { + if (data.selectedIds.length > 1) { + this.select('actionControlsSelector').not('button.single-item').removeAttr('disabled'); + this.select('singleItemActionSelector').attr('disabled', 'disabled'); + } else if (data.selectedIds.length == 1) { + this.select('actionControlsSelector').removeAttr('disabled'); + } else { + this.disableAll(); + } + }; + + this.deleteMail = function(ev, data) { + this.trigger('uiDeleteMail'); + }; + + this.moveMail = function(ev, data) { + this.trigger('uiMoveMail'); + }; + + this.forwardMail = function(ev, data) { + this.trigger('uiForwardMail'); + }; + + this.replyToMail = function(ev, data) { + this.trigger('uiReplyToMail'); + }; + + this.after('initialize', function() { + this.on('.mail-action', 'click', { + 'deleteControlSelector': this.deleteMail, + 'moveControlSelector': this.moveMail, + 'forwardControlSelector': this.forwardMail, + 'replyControlSelector': this.replyToMail + }); + this.on(document, 'uiMailItemSelectionChanged', this.restyleOnSelectionChange); + this.on(document, 'uiFolderSelectionChanged', this.disableAll); + }); + } + } +); + diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_items.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_items.js new file mode 100644 index 0000000000..29b5cfd665 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/mail_items.js @@ -0,0 +1,61 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + './with_select' + ], + + function(defineComponent, withSelect) { + + return defineComponent(mailItems, withSelect); + + function mailItems() { + + this.defaultAttrs({ + deleteFolder: 'trash', + selectedClass: 'selected', + allowMultiSelect: true, + selectionChangedEvent: 'uiMailItemSelectionChanged', + selectedMailItems: [], + selectedFolders: [], + //selectors + itemSelector: 'tr.mail-item', + selectedItemSelector: 'tr.mail-item.selected' + }); + + this.renderItems = function(ev, data) { + this.select('itemContainerSelector').html(data.markup); + //new items, so no selections + this.trigger('uiMailItemSelectionChanged', {selectedIds: []}); + } + + this.updateMailItemSelections = function(ev, data) { + this.attr.selectedMailItems = data.selectedIds; + } + + this.updateFolderSelections = function(ev, data) { + this.attr.selectedFolders = data.selectedIds; + } + + this.requestDeletion = function() { + this.trigger('uiMoveItemsRequested', { + itemIds: this.attr.selectedMailItems, + fromFolder: this.attr.selectedFolders[0], + toFolder: this.attr.deleteFolder + }); + }; + + this.after('initialize', function() { + this.on(document, 'dataMailItemsServed', this.renderItems); + this.on(document, 'uiDeleteMail', this.requestDeletion); + + this.on('uiMailItemSelectionChanged', this.updateMailItemSelections); + this.on(document, 'uiFolderSelectionChanged', this.updateFolderSelections); + + this.trigger('uiMailItemsRequested'); + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/move_to_selector.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/move_to_selector.js new file mode 100644 index 0000000000..e077e6aff3 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/move_to_selector.js @@ -0,0 +1,79 @@ +'use strict'; + +define( + + [ + 'flight/lib/component', + './with_select' + ], + + function(defineComponent, withSelect) { + + return defineComponent(moveToSelector, withSelect); + + function moveToSelector() { + + this.defaultAttrs({ + selectionChangedEvent: 'uiMoveToSelectionChanged', + selectedMailItems: [], + selectedFolders: [], + //selectors + itemSelector: 'li.move-to-item', + selectedItemSelector: 'li.move-to-item.selected' + }); + + this.requestSelectorWidget = function(ev, data) { + this.trigger('uiAvailableFoldersRequested', { + folder: this.attr.selectedFolders[0] + }) + }; + + this.launchSelector = function(ev, data) { + var controlPosition = $(this.attr.moveActionSelector).offset(); + this.$node.html(data.markup).show().css({ + left: controlPosition.left, + top: controlPosition.top + $(this.attr.moveActionSelector).outerHeight(), + width: $(this.attr.moveActionSelector).outerWidth() + }); + window.setTimeout( + (function() { + this.on(document, 'click', this.hideSelector) + }).bind(this), 0); + }; + + this.hideSelector = function() { + this.off(document, 'click', this.hideSelector); + this.$node.hide(); + } + + this.updateMailItemSelections = function(ev, data) { + this.attr.selectedMailItems = data.selectedIds; + } + + this.updateFolderSelections = function(ev, data) { + this.attr.selectedFolders = data.selectedIds; + } + + this.requestMoveTo = function(ev, data) { + this.trigger('uiMoveItemsRequested', { + itemIds: this.attr.selectedMailItems, + fromFolder: this.attr.selectedFolders[0], + toFolder: data.selectedIds[0] + }); + this.$node.hide(); + }; + + this.after('initialize', function() { + //show selector widget + this.on(document, 'uiMoveMail', this.requestSelectorWidget); + this.on(document, 'dataMoveToItemsServed', this.launchSelector); + //listen for other selections + this.on(document, 'uiMailItemSelectionChanged', this.updateMailItemSelections); + this.on(document, 'uiFolderSelectionChanged', this.updateFolderSelections); + //move items + this.on('uiMoveToSelectionChanged', this.requestMoveTo); + + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/with_select.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/with_select.js new file mode 100644 index 0000000000..2a99feaadf --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/component_ui/with_select.js @@ -0,0 +1,64 @@ +'use strict'; + +define( + + function() { + + return withSelect; + + function withSelect() { + + this.defaultAttrs({ + selectedIds: [] + }); + + this.initializeSelections = function() { + this.select('selectedItemSelector').toArray().forEach(function(el) { + this.attr.selectedIds.push(el.getAttribute('id')); + }, this); + }; + + this.getSelectedIds = function() { + return this.attr.selectedIds; + }; + + this.toggleItemSelect = function(ev, data) { + var $item = $(data.el), append; + + if ($item.hasClass(this.attr.selectedClass)) { + this.unselectItem($item); + } else { + append = this.attr.allowMultiSelect && (ev.metaKey || ev.ctrlKey || ev.shiftKey); + this.selectItem($item, append); + } + }; + + this.selectItem = function($item, append) { + if (!append) { + this.select('selectedItemSelector').removeClass(this.attr.selectedClass); + this.attr.selectedIds = []; + } + $item.addClass(this.attr.selectedClass); + + this.attr.selectedIds.push($item.attr('id')); + this.trigger(this.attr.selectionChangedEvent, {selectedIds: this.attr.selectedIds}); + }; + + this.unselectItem = function($item) { + $item.removeClass(this.attr.selectedClass); + + var thisIdIndex = this.attr.selectedIds.indexOf($item.attr('id')); + this.attr.selectedIds.splice(thisIdIndex, 1); + this.trigger(this.attr.selectionChangedEvent, {selectedIds: this.attr.selectedIds}); + }; + + this.after("initialize", function() { + this.on('click', { + 'itemSelector': this.toggleItemSelect + }); + + this.initializeSelections(); + }); + } + } +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/css/custom.css b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/css/custom.css new file mode 100644 index 0000000000..697197a075 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/css/custom.css @@ -0,0 +1,102 @@ +.modal.fade.in { + left: 5%; + top: 10%; + margin: auto auto auto auto; +} + +table { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +td.mailContact, +span.mailSubject, +span.mailMessage { + font-size: 15px; +} + +td.mailContact, +span.mailSubject { + font-weight: bold; +} + +tr.mail-item.selected td, +li.folder-item.selected, +li.move-to-item.selected { + background-color: #D9EDF7; +} + +tr.mail-item.selected:hover td, +li.folder-item.selected:hover, +li.move-to-item.selected:hover { + background-color: #C1E1FF; +} + +li.folder-item:hover, +li.move-to-item:hover { + background-color: #EDEDED; +} + +li.folder-item, +li.move-to-item { + padding: 3px 0; + margin-left: -15px; + font-size: 15px; + cursor:pointer; +} + +li.move-to-item { + text-align: center; + margin-right: -15px; +} + +#new_mail { + width: 100px; +} + +div.compose-box { + position: absolute; + z-index: 10; + background-color: #FFFFFF; + width: 350px; + border: 1px solid; +} + +div.compose-body { + padding: 0; +} + +div.compose-header { + font-size: 15px; +} + +#recipient_select { + width: 90%; + margin-bottom: 0; + font-weight: bold; +} + +div.hint { + border: 1px solid #EAEAEA; + color:#CACACA; +} + +#compose_message { + height: 180px; +} + +#compose_subject, +#compose_message { + font-size: 15px; + padding: 15px; +} + +#move_to_selector { + position: absolute; + z-index: 10; + background-color: #FFFFFF; + border: 1px solid; +} \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/data.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/data.js new file mode 100644 index 0000000000..3a567c2264 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/data.js @@ -0,0 +1,110 @@ +'use strict'; + +define( + function() { + return { + folders: ["inbox", "later", "sent", "trash"], + contacts: [ + { + "id": "contact_342", + "firstName": "Michael", + "lastName": "Smith", + "email": "ms@proxyweb.com" + }, + { + "id": "contact_377", + "firstName": "Mary", + "lastName": "Jones", + "email": "mary@jones.net" + }, + { + "id": "contact_398", + "firstName": "Billy", + "lastName": "Idiot", + "email": "william_idiot@gmail.com" + } + ], + mail: [ + { + "id": "mail_2139", + "contact_id": "contact_342", + "folders": ["inbox"], + "time": 1334891976104, + "subject": "Consectetur adipiscing elit", + "message": "Vestibulum vestibulum varius diam in iaculis. Praesent ultrices dui vitae nibh malesuada non iaculis ante vulputate. Suspendisse feugiat ultricies egestas. Aenean a odio libero. Quisque mollis leo et est euismod sit amet dignissim sapien venenatis. Morbi interdum adipiscing massa" + }, + { + "id": "mail_2143", + "contact_id": "contact_377", + "folders": ["inbox", "later"], + "important": "true", + "time": 1334884976104, + "subject": "Neque porro quisquam velit!!", + "message": "Curabitur sollicitudin mi eget sapien posuere semper. Fusce at neque et lacus luctus vulputate vehicula ac enim" + }, + { + "id": "mail_2154", + "contact_id": "contact_398", + "folders": ["inbox"], + "important": "true", + "unread": "true", + "time": 1334874976199, + "subject": "Proin egestas aliquam :)", + "message": "Aenean nec erat id ipsum faucibus tristique. Nam blandit est lacinia turpis consectetur elementum. Nulla in risus ut sapien dignissim feugiat. Proin ultrices sodales imperdiet. Vestibulum vehicula blandit tincidunt. Vivamus posuere rhoncus orci, porta commodo mauris aliquam nec" + }, + { + "id": "mail_2176", + "contact_id": "contact_377", + "folders": ["inbox"], + "time": 1334884976104, + "subject": "Sed ut perspiciatis unde omnis?", + "message": "laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem." + }, + { + "id": "mail_2191", + "contact_id": "contact_398", + "folders": ["inbox"], + "unread": "true", + "time": 1334874976199, + "subject": "At vero eos et accusamus!", + "message": "Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" + }, + { + "id": "mail_2203", + "contact_id": "contact_377", + "folders": ["later"], + "important": "true", + "time": 1334874576199, + "subject": "Mi netus convallis", + "message": "Egestas morbi at. Curabitur aliquet et commodo nonummy, aliquam quis arcu, sed pellentesque vitae molestie mattis magna, in eget, risus nulla vivamus vulputate" + }, + { + "id": "mail_2212", + "contact_id": "contact_398", + "folders": ["sent"], + "time": 1334874579867, + "subject": "Fusce tristique pretium eros a gravida", + "message": "Proin malesuada" + }, + { + "id": "mail_2021", + "contact_id": "contact_342", + "folders": ["trash"], + "time": 1134874579824, + "subject": "Phasellus vitae interdum nulla.", + "message": "Pellentesque quam eros, mollis quis vulputate eget, pellentesque nec ipsum. Cras dignissim fringilla ligula, ac ullamcorper dui convallis blandit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam id nunc ac orci hendrerit faucibus vel in ante. Mauris nec est turpis, ut fringilla mi. Suspendisse vel tortor at nulla facilisis venenatis in sit amet ligula." + }, + { + "id": "mail_1976", + "contact_id": "contact_377", + "folders": ["trash"], + "time": 1034874579813, + "subject": "Fusce tristique pretium :(", + "message": "aliquam quis arcu." + } + ] + }; + return data; + } +); + diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/templates.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/templates.js new file mode 100644 index 0000000000..99625bd830 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/app/templates.js @@ -0,0 +1,62 @@ +'use strict'; + +define( + function() { + var mailItem = + '{{#mailItems}}\ + \ + {{#important}}\ + Important\ + {{/important}}\ + {{^important}}\ +  \ + {{/important}}\ + {{name}}\ + \ + \ + {{formattedSubject}}\ + \ + \ + - {{formattedMessage}}\ + \ + \ + \ + {{/mailItems}}'; + + var composeBox = + '\ + \ + '; + + var moveToSelector = + ''; + + return { + mailItem: mailItem, + composeBox: composeBox, + moveToSelector: moveToSelector + } + } + +); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.css b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.css new file mode 100644 index 0000000000..a3352d774c --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.css @@ -0,0 +1,1092 @@ +/*! + * Bootstrap Responsive v2.2.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +@-ms-viewport { + width: device-width; +} + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + right: 10px; + left: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .dropdown-menu a:hover { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:hover { + background-color: #111111; + } + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.min.css b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.min.css new file mode 100644 index 0000000000..5cb833ff08 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.2.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.css b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.css new file mode 100644 index 0000000000..54d06c6ec4 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.css @@ -0,0 +1,2470 @@ +/*! + * Bootstrap v1.4.0 + * + * Copyright 2011 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + * Date: Sun Dec 25 20:18:31 PST 2011 + */ +/* Reset.less + * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). + * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ +html, body { + margin: 0; + padding: 0; +} +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +cite, +code, +del, +dfn, +em, +img, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +dd, +dl, +dt, +li, +ol, +ul, +fieldset, +form, +label, +legend, +button, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td { + margin: 0; + padding: 0; + border: 0; + font-weight: normal; + font-style: normal; + font-size: 100%; + line-height: 1; + font-family: inherit; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +ol, ul { + list-style: none; +} +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} +html { + overflow-y: scroll; + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted; +} +a:hover, a:active { + outline: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; +} +audio:not([controls]) { + display: none; +} +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; + -ms-interpolation-mode: bicubic; +} +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, input { + line-height: normal; + *overflow: visible; +} +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +textarea { + overflow: auto; + vertical-align: top; +} +/* Variables.less + * Variables to customize the look and feel of Bootstrap + * ----------------------------------------------------- */ +/* Mixins.less + * Snippets of reusable CSS to develop faster and keep code readable + * ----------------------------------------------------------------- */ +/* + * Scaffolding + * Basic and global styles for generating a grid system, structural layout, and page templates + * ------------------------------------------------------------------------------------------- */ +body { + background-color: #ffffff; + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 18px; + color: #404040; +} +.container { + width: 940px; + margin-left: auto; + margin-right: auto; + zoom: 1; +} +.container:before, .container:after { + display: table; + content: ""; + zoom: 1; +} +.container:after { + clear: both; +} +.container-fluid { + position: relative; + min-width: 940px; + padding-left: 20px; + padding-right: 20px; + zoom: 1; +} +.container-fluid:before, .container-fluid:after { + display: table; + content: ""; + zoom: 1; +} +.container-fluid:after { + clear: both; +} +.container-fluid > .sidebar { + position: absolute; + top: 0; + left: 20px; + width: 220px; +} +.container-fluid > .content { + margin-left: 240px; +} +a { + color: #0069d6; + text-decoration: none; + line-height: inherit; + font-weight: inherit; +} +a:hover { + color: #00438a; + text-decoration: underline; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.row { + zoom: 1; + margin-left: -20px; +} +.row:before, .row:after { + display: table; + content: ""; + zoom: 1; +} +.row:after { + clear: both; +} +.row > [class*="span"] { + display: inline; + float: left; + margin-left: 20px; +} +.span1 { + width: 40px; +} +.span2 { + width: 100px; +} +.span3 { + width: 160px; +} +.span4 { + width: 220px; +} +.span5 { + width: 280px; +} +.span6 { + width: 340px; +} +.span7 { + width: 400px; +} +.span8 { + width: 460px; +} +.span9 { + width: 520px; +} +.span10 { + width: 580px; +} +.span11 { + width: 640px; +} +.span12 { + width: 700px; +} +.span13 { + width: 760px; +} +.span14 { + width: 820px; +} +.span15 { + width: 880px; +} +.span16 { + width: 940px; +} +.span17 { + width: 1000px; +} +.span18 { + width: 1060px; +} +.span19 { + width: 1120px; +} +.span20 { + width: 1180px; +} +.span21 { + width: 1240px; +} +.span22 { + width: 1300px; +} +.span23 { + width: 1360px; +} +.span24 { + width: 1420px; +} +.row > .offset1 { + margin-left: 80px; +} +.row > .offset2 { + margin-left: 140px; +} +.row > .offset3 { + margin-left: 200px; +} +.row > .offset4 { + margin-left: 260px; +} +.row > .offset5 { + margin-left: 320px; +} +.row > .offset6 { + margin-left: 380px; +} +.row > .offset7 { + margin-left: 440px; +} +.row > .offset8 { + margin-left: 500px; +} +.row > .offset9 { + margin-left: 560px; +} +.row > .offset10 { + margin-left: 620px; +} +.row > .offset11 { + margin-left: 680px; +} +.row > .offset12 { + margin-left: 740px; +} +.span-one-third { + width: 300px; +} +.span-two-thirds { + width: 620px; +} +.row > .offset-one-third { + margin-left: 340px; +} +.row > .offset-two-thirds { + margin-left: 660px; +} +/* Typography.less + * Headings, body text, lists, code, and more for a versatile and durable typography system + * ---------------------------------------------------------------------------------------- */ +p { + font-size: 13px; + font-weight: normal; + line-height: 18px; + margin-bottom: 9px; +} +p small { + font-size: 11px; + color: #bfbfbf; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: bold; + color: #404040; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + color: #bfbfbf; +} +h1 { + margin-bottom: 18px; + font-size: 30px; + line-height: 36px; +} +h1 small { + font-size: 18px; +} +h2 { + font-size: 24px; + line-height: 36px; +} +h2 small { + font-size: 14px; +} +h3, +h4, +h5, +h6 { + line-height: 36px; +} +h3 { + font-size: 18px; +} +h3 small { + font-size: 14px; +} +h4 { + font-size: 16px; +} +h4 small { + font-size: 12px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 13px; + color: #bfbfbf; + text-transform: uppercase; +} +ul, ol { + margin: 0 0 18px 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li { + line-height: 18px; + color: #808080; +} +ul.unstyled { + list-style: none; + margin-left: 0; +} +dl { + margin-bottom: 18px; +} +dl dt, dl dd { + line-height: 18px; +} +dl dt { + font-weight: bold; +} +dl dd { + margin-left: 9px; +} +hr { + margin: 20px 0 19px; + border: 0; + border-bottom: 1px solid #eee; +} +strong { + font-style: inherit; + font-weight: bold; +} +em { + font-style: italic; + font-weight: inherit; + line-height: inherit; +} +.muted { + color: #bfbfbf; +} +blockquote { + margin-bottom: 18px; + border-left: 5px solid #eee; + padding-left: 15px; +} +blockquote p { + font-size: 14px; + font-weight: 300; + line-height: 18px; + margin-bottom: 0; +} +blockquote small { + display: block; + font-size: 12px; + font-weight: 300; + line-height: 18px; + color: #bfbfbf; +} +blockquote small:before { + content: '\2014 \00A0'; +} +address { + display: block; + line-height: 18px; + margin-bottom: 18px; +} +code, pre { + padding: 0 3px 2px; + font-family: Monaco, Andale Mono, Courier New, monospace; + font-size: 12px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +code { + background-color: #fee9cc; + color: rgba(0, 0, 0, 0.75); + padding: 1px 3px; +} +pre { + background-color: #f5f5f5; + display: block; + padding: 8.5px; + margin: 0 0 18px; + line-height: 18px; + font-size: 12px; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} +/* Forms.less + * Base styles for various input types, form layouts, and states + * ------------------------------------------------------------- */ +form { + margin-bottom: 18px; +} +fieldset { + margin-bottom: 18px; + padding-top: 18px; +} +fieldset legend { + display: block; + padding-left: 150px; + font-size: 19.5px; + line-height: 1; + color: #404040; + *padding: 0 0 5px 145px; + /* IE6-7 */ + + *line-height: 1.5; + /* IE6-7 */ + +} +form .clearfix { + margin-bottom: 18px; + zoom: 1; +} +form .clearfix:before, form .clearfix:after { + display: table; + content: ""; + zoom: 1; +} +form .clearfix:after { + clear: both; +} +label, +input, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: normal; +} +label { + padding-top: 6px; + font-size: 13px; + line-height: 18px; + float: left; + width: 130px; + text-align: right; + color: #404040; +} +form .input { + margin-left: 150px; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; +} +input, +textarea, +select, +.uneditable-input { + display: inline-block; + width: 210px; + height: 18px; + padding: 4px; + font-size: 13px; + line-height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +select { + padding: initial; +} +input[type=checkbox], input[type=radio] { + width: auto; + height: auto; + padding: 0; + margin: 3px 0; + *margin-top: 0; + /* IE6-7 */ + + line-height: normal; + border: none; +} +input[type=file] { + background-color: #ffffff; + padding: initial; + border: initial; + line-height: initial; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +input[type=button], input[type=reset], input[type=submit] { + width: auto; + height: auto; +} +select, input[type=file] { + height: 27px; + *height: auto; + line-height: 27px; + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + +} +select[multiple] { + height: inherit; + background-color: #ffffff; +} +textarea { + height: auto; +} +.uneditable-input { + background-color: #ffffff; + display: block; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + cursor: not-allowed; +} +:-moz-placeholder { + color: #bfbfbf; +} +::-webkit-input-placeholder { + color: #bfbfbf; +} +input, textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input:focus, textarea:focus { + outline: 0; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} +input[type=file]:focus, input[type=checkbox]:focus, select:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + outline: 1px dotted #666; +} +form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline { + color: #b94a48; +} +form .clearfix.error input, form .clearfix.error textarea { + color: #b94a48; + border-color: #ee5f5b; +} +form .clearfix.error input:focus, form .clearfix.error textarea:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} +form .clearfix.error .input-prepend .add-on, form .clearfix.error .input-append .add-on { + color: #b94a48; + background-color: #fce6e6; + border-color: #b94a48; +} +form .clearfix.warning > label, form .clearfix.warning .help-block, form .clearfix.warning .help-inline { + color: #c09853; +} +form .clearfix.warning input, form .clearfix.warning textarea { + color: #c09853; + border-color: #ccae64; +} +form .clearfix.warning input:focus, form .clearfix.warning textarea:focus { + border-color: #be9a3f; + -webkit-box-shadow: 0 0 6px #e5d6b1; + -moz-box-shadow: 0 0 6px #e5d6b1; + box-shadow: 0 0 6px #e5d6b1; +} +form .clearfix.warning .input-prepend .add-on, form .clearfix.warning .input-append .add-on { + color: #c09853; + background-color: #d2b877; + border-color: #c09853; +} +form .clearfix.success > label, form .clearfix.success .help-block, form .clearfix.success .help-inline { + color: #468847; +} +form .clearfix.success input, form .clearfix.success textarea { + color: #468847; + border-color: #57a957; +} +form .clearfix.success input:focus, form .clearfix.success textarea:focus { + border-color: #458845; + -webkit-box-shadow: 0 0 6px #9acc9a; + -moz-box-shadow: 0 0 6px #9acc9a; + box-shadow: 0 0 6px #9acc9a; +} +form .clearfix.success .input-prepend .add-on, form .clearfix.success .input-append .add-on { + color: #468847; + background-color: #bcddbc; + border-color: #468847; +} +.input-mini, +input.mini, +textarea.mini, +select.mini { + width: 60px; +} +.input-small, +input.small, +textarea.small, +select.small { + width: 90px; +} +.input-medium, +input.medium, +textarea.medium, +select.medium { + width: 150px; +} +.input-large, +input.large, +textarea.large, +select.large { + width: 210px; +} +.input-xlarge, +input.xlarge, +textarea.xlarge, +select.xlarge { + width: 270px; +} +.input-xxlarge, +input.xxlarge, +textarea.xxlarge, +select.xxlarge { + width: 530px; +} +textarea.xxlarge { + overflow-y: auto; +} +input.span1, textarea.span1 { + display: inline-block; + float: none; + width: 30px; + margin-left: 0; +} +input.span2, textarea.span2 { + display: inline-block; + float: none; + width: 90px; + margin-left: 0; +} +input.span3, textarea.span3 { + display: inline-block; + float: none; + width: 150px; + margin-left: 0; +} +input.span4, textarea.span4 { + display: inline-block; + float: none; + width: 210px; + margin-left: 0; +} +input.span5, textarea.span5 { + display: inline-block; + float: none; + width: 270px; + margin-left: 0; +} +input.span6, textarea.span6 { + display: inline-block; + float: none; + width: 330px; + margin-left: 0; +} +input.span7, textarea.span7 { + display: inline-block; + float: none; + width: 390px; + margin-left: 0; +} +input.span8, textarea.span8 { + display: inline-block; + float: none; + width: 450px; + margin-left: 0; +} +input.span9, textarea.span9 { + display: inline-block; + float: none; + width: 510px; + margin-left: 0; +} +input.span10, textarea.span10 { + display: inline-block; + float: none; + width: 570px; + margin-left: 0; +} +input.span11, textarea.span11 { + display: inline-block; + float: none; + width: 630px; + margin-left: 0; +} +input.span12, textarea.span12 { + display: inline-block; + float: none; + width: 690px; + margin-left: 0; +} +input.span13, textarea.span13 { + display: inline-block; + float: none; + width: 750px; + margin-left: 0; +} +input.span14, textarea.span14 { + display: inline-block; + float: none; + width: 810px; + margin-left: 0; +} +input.span15, textarea.span15 { + display: inline-block; + float: none; + width: 870px; + margin-left: 0; +} +input.span16, textarea.span16 { + display: inline-block; + float: none; + width: 930px; + margin-left: 0; +} +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + background-color: #f5f5f5; + border-color: #ddd; + cursor: not-allowed; +} +.actions { + background: #f5f5f5; + margin-top: 18px; + margin-bottom: 18px; + padding: 17px 20px 18px 150px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; +} +.actions .secondary-action { + float: right; +} +.actions .secondary-action a { + line-height: 30px; +} +.actions .secondary-action a:hover { + text-decoration: underline; +} +.help-inline, .help-block { + font-size: 13px; + line-height: 18px; + color: #bfbfbf; +} +.help-inline { + padding-left: 5px; + *position: relative; + /* IE6-7 */ + + *top: -5px; + /* IE6-7 */ + +} +.help-block { + display: block; + max-width: 600px; +} +.inline-inputs { + color: #808080; +} +.inline-inputs span { + padding: 0 2px 0 1px; +} +.input-prepend input, .input-append input { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-prepend .add-on, .input-append .add-on { + position: relative; + background: #f5f5f5; + border: 1px solid #ccc; + z-index: 2; + float: left; + display: block; + width: auto; + min-width: 16px; + height: 18px; + padding: 4px 4px 4px 5px; + margin-right: -1px; + font-weight: normal; + line-height: 18px; + color: #bfbfbf; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-prepend .active, .input-append .active { + background: #a9dba9; + border-color: #46a546; +} +.input-prepend .add-on { + *margin-top: 1px; + /* IE6-7 */ + +} +.input-append input { + float: left; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-append .add-on { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; + margin-right: 0; + margin-left: -1px; +} +.inputs-list { + margin: 0 0 5px; + width: 100%; +} +.inputs-list li { + display: block; + padding: 0; + width: 100%; +} +.inputs-list label { + display: block; + float: none; + width: auto; + padding: 0; + margin-left: 20px; + line-height: 18px; + text-align: left; + white-space: normal; +} +.inputs-list label strong { + color: #808080; +} +.inputs-list label small { + font-size: 11px; + font-weight: normal; +} +.inputs-list .inputs-list { + margin-left: 25px; + margin-bottom: 10px; + padding-top: 0; +} +.inputs-list:first-child { + padding-top: 6px; +} +.inputs-list li + li { + padding-top: 2px; +} +.inputs-list input[type=radio], .inputs-list input[type=checkbox] { + margin-bottom: 0; + margin-left: -20px; + float: left; +} +.form-stacked { + padding-left: 20px; +} +.form-stacked fieldset { + padding-top: 9px; +} +.form-stacked legend { + padding-left: 0; +} +.form-stacked label { + display: block; + float: none; + width: auto; + font-weight: bold; + text-align: left; + line-height: 20px; + padding-top: 0; +} +.form-stacked .clearfix { + margin-bottom: 9px; +} +.form-stacked .clearfix div.input { + margin-left: 0; +} +.form-stacked .inputs-list { + margin-bottom: 0; +} +.form-stacked .inputs-list li { + padding-top: 0; +} +.form-stacked .inputs-list li label { + font-weight: normal; + padding-top: 0; +} +.form-stacked div.clearfix.error { + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + margin-top: 0; + margin-left: -10px; +} +.form-stacked .actions { + margin-left: -20px; + padding-left: 20px; +} +/* + * Tables.less + * Tables for, you guessed it, tabular data + * ---------------------------------------- */ +table { + width: 100%; + margin-bottom: 18px; + padding: 0; + font-size: 13px; + border-collapse: collapse; +} +table th, table td { + padding: 10px 10px 9px; + line-height: 18px; + text-align: left; +} +table th { + padding-top: 9px; + font-weight: bold; + vertical-align: middle; +} +table td { + vertical-align: top; + border-top: 1px solid #ddd; +} +table tbody th { + border-top: 1px solid #ddd; + vertical-align: top; +} +.condensed-table th, .condensed-table td { + padding: 5px 5px 4px; +} +.bordered-table { + border: 1px solid #ddd; + border-collapse: separate; + *border-collapse: collapse; + /* IE7, collapse table to remove spacing */ + + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.bordered-table th + th, .bordered-table td + td, .bordered-table th + td { + border-left: 1px solid #ddd; +} +.bordered-table thead tr:first-child th:first-child, .bordered-table tbody tr:first-child td:first-child { + -webkit-border-radius: 4px 0 0 0; + -moz-border-radius: 4px 0 0 0; + border-radius: 4px 0 0 0; +} +.bordered-table thead tr:first-child th:last-child, .bordered-table tbody tr:first-child td:last-child { + -webkit-border-radius: 0 4px 0 0; + -moz-border-radius: 0 4px 0 0; + border-radius: 0 4px 0 0; +} +.bordered-table tbody tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; +} +.bordered-table tbody tr:last-child td:last-child { + -webkit-border-radius: 0 0 4px 0; + -moz-border-radius: 0 0 4px 0; + border-radius: 0 0 4px 0; +} +table .span1 { + width: 20px; +} +table .span2 { + width: 60px; +} +table .span3 { + width: 100px; +} +table .span4 { + width: 140px; +} +table .span5 { + width: 180px; +} +table .span6 { + width: 220px; +} +table .span7 { + width: 260px; +} +table .span8 { + width: 300px; +} +table .span9 { + width: 340px; +} +table .span10 { + width: 380px; +} +table .span11 { + width: 420px; +} +table .span12 { + width: 460px; +} +table .span13 { + width: 500px; +} +table .span14 { + width: 540px; +} +table .span15 { + width: 580px; +} +table .span16 { + width: 620px; +} +.zebra-striped tbody tr:nth-child(odd) td, .zebra-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} +.zebra-striped tbody tr:hover td, .zebra-striped tbody tr:hover th { + background-color: #f5f5f5; +} +table .header { + cursor: pointer; +} +table .header:after { + content: ""; + float: right; + margin-top: 7px; + border-width: 0 4px 4px; + border-style: solid; + border-color: #000 transparent; + visibility: hidden; +} +table .headerSortUp, table .headerSortDown { + background-color: rgba(141, 192, 219, 0.25); + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); +} +table .header:hover:after { + visibility: visible; +} +table .headerSortDown:after, table .headerSortDown:hover:after { + visibility: visible; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .headerSortUp:after { + border-bottom: none; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #000; + visibility: visible; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + filter: alpha(opacity=60); + -khtml-opacity: 0.6; + -moz-opacity: 0.6; + opacity: 0.6; +} +table .blue { + color: #049cdb; + border-bottom-color: #049cdb; +} +table .headerSortUp.blue, table .headerSortDown.blue { + background-color: #ade6fe; +} +table .green { + color: #46a546; + border-bottom-color: #46a546; +} +table .headerSortUp.green, table .headerSortDown.green { + background-color: #cdeacd; +} +table .red { + color: #9d261d; + border-bottom-color: #9d261d; +} +table .headerSortUp.red, table .headerSortDown.red { + background-color: #f4c8c5; +} +table .yellow { + color: #ffc40d; + border-bottom-color: #ffc40d; +} +table .headerSortUp.yellow, table .headerSortDown.yellow { + background-color: #fff6d9; +} +table .orange { + color: #f89406; + border-bottom-color: #f89406; +} +table .headerSortUp.orange, table .headerSortDown.orange { + background-color: #fee9cc; +} +table .purple { + color: #7a43b6; + border-bottom-color: #7a43b6; +} +table .headerSortUp.purple, table .headerSortDown.purple { + background-color: #e2d5f0; +} +/* Patterns.less + * Repeatable UI elements outside the base styles provided from the scaffolding + * ---------------------------------------------------------------------------- */ +.topbar { + height: 40px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 10000; + overflow: visible; +} +.topbar a { + color: #bfbfbf; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.topbar h3 a:hover, .topbar .brand:hover, .topbar ul .active > a { + background-color: #333; + background-color: rgba(255, 255, 255, 0.05); + color: #ffffff; + text-decoration: none; +} +.topbar h3 { + position: relative; +} +.topbar h3 a, .topbar .brand { + float: left; + display: block; + padding: 8px 20px 12px; + margin-left: -20px; + color: #ffffff; + font-size: 20px; + font-weight: 200; + line-height: 1; +} +.topbar p { + margin: 0; + line-height: 40px; +} +.topbar p a:hover { + background-color: transparent; + color: #ffffff; +} +.topbar form { + float: left; + margin: 5px 0 0 0; + position: relative; + filter: alpha(opacity=100); + -khtml-opacity: 1; + -moz-opacity: 1; + opacity: 1; +} +.topbar form.pull-right { + float: right; +} +.topbar input { + background-color: #444; + background-color: rgba(255, 255, 255, 0.3); + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: normal; + font-weight: 13px; + line-height: 1; + padding: 4px 9px; + color: #ffffff; + color: rgba(255, 255, 255, 0.75); + border: 1px solid #111; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} +.topbar input:-moz-placeholder { + color: #e6e6e6; +} +.topbar input::-webkit-input-placeholder { + color: #e6e6e6; +} +.topbar input:hover { + background-color: #bfbfbf; + background-color: rgba(255, 255, 255, 0.5); + color: #ffffff; +} +.topbar input:focus, .topbar input.focused { + outline: 0; + background-color: #ffffff; + color: #404040; + text-shadow: 0 1px 0 #ffffff; + border: 0; + padding: 5px 10px; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} +.topbar-inner, .topbar .fill { + background-color: #222; + background-color: #222222; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} +.topbar div > ul, .nav { + display: block; + float: left; + margin: 0 10px 0 0; + position: relative; + left: 0; +} +.topbar div > ul > li, .nav > li { + display: block; + float: left; +} +.topbar div > ul a, .nav a { + display: block; + float: none; + padding: 10px 10px 11px; + line-height: 19px; + text-decoration: none; +} +.topbar div > ul a:hover, .nav a:hover { + color: #ffffff; + text-decoration: none; +} +.topbar div > ul .active > a, .nav .active > a { + background-color: #222; + background-color: rgba(0, 0, 0, 0.5); +} +.topbar div > ul.secondary-nav, .nav.secondary-nav { + float: right; + margin-left: 10px; + margin-right: 0; +} +.topbar div > ul.secondary-nav .menu-dropdown, +.nav.secondary-nav .menu-dropdown, +.topbar div > ul.secondary-nav .dropdown-menu, +.nav.secondary-nav .dropdown-menu { + right: 0; + border: 0; +} +.topbar div > ul a.menu:hover, +.nav a.menu:hover, +.topbar div > ul li.open .menu, +.nav li.open .menu, +.topbar div > ul .dropdown-toggle:hover, +.nav .dropdown-toggle:hover, +.topbar div > ul .dropdown.open .dropdown-toggle, +.nav .dropdown.open .dropdown-toggle { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown, +.nav .menu-dropdown, +.topbar div > ul .dropdown-menu, +.nav .dropdown-menu { + background-color: #333; +} +.topbar div > ul .menu-dropdown a.menu, +.nav .menu-dropdown a.menu, +.topbar div > ul .dropdown-menu a.menu, +.nav .dropdown-menu a.menu, +.topbar div > ul .menu-dropdown .dropdown-toggle, +.nav .menu-dropdown .dropdown-toggle, +.topbar div > ul .dropdown-menu .dropdown-toggle, +.nav .dropdown-menu .dropdown-toggle { + color: #ffffff; +} +.topbar div > ul .menu-dropdown a.menu.open, +.nav .menu-dropdown a.menu.open, +.topbar div > ul .dropdown-menu a.menu.open, +.nav .dropdown-menu a.menu.open, +.topbar div > ul .menu-dropdown .dropdown-toggle.open, +.nav .menu-dropdown .dropdown-toggle.open, +.topbar div > ul .dropdown-menu .dropdown-toggle.open, +.nav .dropdown-menu .dropdown-toggle.open { + background: #444; + background: rgba(255, 255, 255, 0.05); +} +.topbar div > ul .menu-dropdown li a, +.nav .menu-dropdown li a, +.topbar div > ul .dropdown-menu li a, +.nav .dropdown-menu li a { + color: #999; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); +} +.topbar div > ul .menu-dropdown li a:hover, +.nav .menu-dropdown li a:hover, +.topbar div > ul .dropdown-menu li a:hover, +.nav .dropdown-menu li a:hover { + background-color: #191919; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919)); + background-image: -moz-linear-gradient(top, #292929, #191919); + background-image: -ms-linear-gradient(top, #292929, #191919); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919)); + background-image: -webkit-linear-gradient(top, #292929, #191919); + background-image: -o-linear-gradient(top, #292929, #191919); + background-image: linear-gradient(top, #292929, #191919); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0); + color: #ffffff; +} +.topbar div > ul .menu-dropdown .active a, +.nav .menu-dropdown .active a, +.topbar div > ul .dropdown-menu .active a, +.nav .dropdown-menu .active a { + color: #ffffff; +} +.topbar div > ul .menu-dropdown .divider, +.nav .menu-dropdown .divider, +.topbar div > ul .dropdown-menu .divider, +.nav .dropdown-menu .divider { + background-color: #222; + border-color: #444; +} +.topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a { + padding: 4px 15px; +} +li.menu, .dropdown { + position: relative; +} +a.menu:after, .dropdown-toggle:after { + width: 0; + height: 0; + display: inline-block; + content: "↓"; + text-indent: -99999px; + vertical-align: top; + margin-top: 8px; + margin-left: 4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #ffffff; + filter: alpha(opacity=50); + -khtml-opacity: 0.5; + -moz-opacity: 0.5; + opacity: 0.5; +} +.menu-dropdown, .dropdown-menu { + background-color: #ffffff; + float: left; + display: none; + position: absolute; + top: 40px; + z-index: 900; + min-width: 160px; + max-width: 220px; + _width: 160px; + margin-left: 0; + margin-right: 0; + padding: 6px 0; + zoom: 1; + border-color: #999; + border-color: rgba(0, 0, 0, 0.2); + border-style: solid; + border-width: 0 1px 1px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.menu-dropdown li, .dropdown-menu li { + float: none; + display: block; + background-color: none; +} +.menu-dropdown .divider, .dropdown-menu .divider { + height: 1px; + margin: 5px 0; + overflow: hidden; + background-color: #eee; + border-bottom: 1px solid #ffffff; +} +.topbar .dropdown-menu a, .dropdown-menu a { + display: block; + padding: 4px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #808080; + text-shadow: 0 1px 0 #ffffff; +} +.topbar .dropdown-menu a:hover, +.dropdown-menu a:hover, +.topbar .dropdown-menu a.hover, +.dropdown-menu a.hover { + background-color: #dddddd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd)); + background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); + background-image: -ms-linear-gradient(top, #eeeeee, #dddddd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)); + background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd); + background-image: -o-linear-gradient(top, #eeeeee, #dddddd); + background-image: linear-gradient(top, #eeeeee, #dddddd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0); + color: #404040; + text-decoration: none; + -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); +} +.open .menu, +.dropdown.open .menu, +.open .dropdown-toggle, +.dropdown.open .dropdown-toggle { + color: #ffffff; + background: #ccc; + background: rgba(0, 0, 0, 0.3); +} +.open .menu-dropdown, +.dropdown.open .menu-dropdown, +.open .dropdown-menu, +.dropdown.open .dropdown-menu { + display: block; +} +.tabs, .pills { + margin: 0 0 18px; + padding: 0; + list-style: none; + zoom: 1; +} +.tabs:before, +.pills:before, +.tabs:after, +.pills:after { + display: table; + content: ""; + zoom: 1; +} +.tabs:after, .pills:after { + clear: both; +} +.tabs > li, .pills > li { + float: left; +} +.tabs > li > a, .pills > li > a { + display: block; +} +.tabs { + border-color: #ddd; + border-style: solid; + border-width: 0 0 1px; +} +.tabs > li { + position: relative; + margin-bottom: -1px; +} +.tabs > li > a { + padding: 0 15px; + margin-right: 2px; + line-height: 34px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.tabs > li > a:hover { + text-decoration: none; + background-color: #eee; + border-color: #eee #eee #ddd; +} +.tabs .active > a, .tabs .active > a:hover { + color: #808080; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.tabs .menu-dropdown, .tabs .dropdown-menu { + top: 35px; + border-width: 1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} +.tabs a.menu:after, .tabs .dropdown-toggle:after { + border-top-color: #999; + margin-top: 15px; + margin-left: 5px; +} +.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { + border-color: #999; +} +.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { + border-top-color: #555; +} +.pills a { + margin: 5px 3px 5px 0; + padding: 0 15px; + line-height: 30px; + text-shadow: 0 1px 1px #ffffff; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pills a:hover { + color: #ffffff; + text-decoration: none; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #00438a; +} +.pills .active a { + color: #ffffff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #0069d6; +} +.pills-vertical > li { + float: none; +} +.tab-content > .tab-pane, +.pill-content > .pill-pane, +.tab-content > div, +.pill-content > div { + display: none; +} +.tab-content > .active, .pill-content > .active { + display: block; +} +.breadcrumb { + padding: 7px 14px; + margin: 0 0 18px; + background-color: #f5f5f5; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5)); + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} +.breadcrumb li { + display: inline; + text-shadow: 0 1px 0 #ffffff; +} +.breadcrumb .divider { + padding: 0 5px; + color: #bfbfbf; +} +.breadcrumb .active a { + color: #404040; +} +.hero-unit { + background-color: #f5f5f5; + margin-bottom: 30px; + padding: 60px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; +} +.hero-unit p { + font-size: 18px; + font-weight: 200; + line-height: 27px; +} +footer { + margin-top: 17px; + padding-top: 17px; + border-top: 1px solid #eee; +} +.page-header { + margin-bottom: 17px; + border-bottom: 1px solid #ddd; + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.page-header h1 { + margin-bottom: 8px; +} +.btn.danger, +.alert-message.danger, +.btn.danger:hover, +.alert-message.danger:hover, +.btn.error, +.alert-message.error, +.btn.error:hover, +.alert-message.error:hover, +.btn.success, +.alert-message.success, +.btn.success:hover, +.alert-message.success:hover, +.btn.info, +.alert-message.info, +.btn.info:hover, +.alert-message.info:hover { + color: #ffffff; +} +.btn .close, .alert-message .close { + font-family: Arial, sans-serif; + line-height: 18px; +} +.btn.danger, +.alert-message.danger, +.btn.error, +.alert-message.error { + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.success, .alert-message.success { + background-color: #57a957; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #57a957 #57a957 #3d773d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.info, .alert-message.info { + background-color: #339bb9; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9)); + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #339bb9 #339bb9 #22697d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn { + cursor: pointer; + display: inline-block; + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + padding: 5px 14px 6px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + -ms-transition: 0.1s linear all; + -o-transition: 0.1s linear all; + transition: 0.1s linear all; +} +.btn:hover { + background-position: 0 -15px; + color: #333; + text-decoration: none; +} +.btn:focus { + outline: 1px dotted #666; +} +.btn.primary { + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn.active, .btn:active { + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.btn.disabled { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn[disabled] { + cursor: default; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=65); + -khtml-opacity: 0.65; + -moz-opacity: 0.65; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn.large { + font-size: 15px; + line-height: normal; + padding: 9px 14px 9px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.btn.small { + padding: 7px 9px 7px; + font-size: 11px; +} +:root .alert-message, :root .btn { + border-radius: 0 \0; +} +button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { + padding: 0; + border: 0; +} +.close { + float: right; + color: #000000; + font-size: 20px; + font-weight: bold; + line-height: 13.5px; + text-shadow: 0 1px 0 #ffffff; + filter: alpha(opacity=25); + -khtml-opacity: 0.25; + -moz-opacity: 0.25; + opacity: 0.25; +} +.close:hover { + color: #000000; + text-decoration: none; + filter: alpha(opacity=40); + -khtml-opacity: 0.4; + -moz-opacity: 0.4; + opacity: 0.4; +} +.alert-message { + position: relative; + padding: 7px 15px; + margin-bottom: 18px; + color: #404040; + background-color: #eedc94; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); + background-image: -moz-linear-gradient(top, #fceec1, #eedc94); + background-image: -ms-linear-gradient(top, #fceec1, #eedc94); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); + background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); + background-image: -o-linear-gradient(top, #fceec1, #eedc94); + background-image: linear-gradient(top, #fceec1, #eedc94); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #eedc94 #eedc94 #e4c652; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message .close { + margin-top: 1px; + *margin-top: 0; +} +.alert-message a { + font-weight: bold; + color: #404040; +} +.alert-message.danger p a, +.alert-message.error p a, +.alert-message.success p a, +.alert-message.info p a { + color: #ffffff; +} +.alert-message h5 { + line-height: 18px; +} +.alert-message p { + margin-bottom: 0; +} +.alert-message div { + margin-top: 5px; + margin-bottom: 2px; + line-height: 28px; +} +.alert-message .btn { + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message.block-message { + background-image: none; + background-color: #fdf5d9; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + padding: 14px; + border-color: #fceec1; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.alert-message.block-message ul, .alert-message.block-message p { + margin-right: 30px; +} +.alert-message.block-message ul { + margin-bottom: 0; +} +.alert-message.block-message li { + color: #404040; +} +.alert-message.block-message .alert-actions { + margin-top: 5px; +} +.alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info { + color: #404040; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.alert-message.block-message.error { + background-color: #fddfde; + border-color: #fbc7c6; +} +.alert-message.block-message.success { + background-color: #d1eed1; + border-color: #bfe7bf; +} +.alert-message.block-message.info { + background-color: #ddf4fb; + border-color: #c6edf9; +} +.alert-message.block-message.danger p a, +.alert-message.block-message.error p a, +.alert-message.block-message.success p a, +.alert-message.block-message.info p a { + color: #404040; +} +.pagination { + height: 36px; + margin: 18px 0; +} +.pagination ul { + float: left; + margin: 0; + border: 1px solid #ddd; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} +.pagination li { + display: inline; +} +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + border-right: 1px solid; + border-right-color: #ddd; + border-right-color: rgba(0, 0, 0, 0.15); + *border-right-color: #ddd; + /* IE6-7 */ + + text-decoration: none; +} +.pagination a:hover, .pagination .active a { + background-color: #c7eefe; +} +.pagination .disabled a, .pagination .disabled a:hover { + background-color: transparent; + color: #bfbfbf; +} +.pagination .next a { + border: 0; +} +.well { + background-color: #f5f5f5; + margin-bottom: 20px; + padding: 19px; + min-height: 20px; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.modal-backdrop { + background-color: #000000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, .modal-backdrop.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 11000; + max-height: 500px; + overflow: auto; + width: 560px; + margin: -250px 0 0 -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + /* IE6-7 */ + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal .close { + margin-top: 7px; +} +.modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 50%; +} +.modal-header { + border-bottom: 1px solid #eee; + padding: 5px 15px; +} +.modal-body { + padding: 15px; +} +.modal-body form { + margin-bottom: 0; +} +.modal-footer { + background-color: #f5f5f5; + padding: 14px 15px 15px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + zoom: 1; + margin-bottom: 0; +} +.modal-footer:before, .modal-footer:after { + display: table; + content: ""; + zoom: 1; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn { + float: right; + margin-left: 5px; +} +.modal .popover, .modal .twipsy { + z-index: 12000; +} +.twipsy { + display: block; + position: absolute; + visibility: visible; + padding: 5px; + font-size: 11px; + z-index: 1000; + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.twipsy.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +.twipsy.above .twipsy-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.twipsy.left .twipsy-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.twipsy.below .twipsy-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.twipsy.right .twipsy-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.twipsy-inner { + padding: 3px 8px; + background-color: #000000; + color: white; + text-align: center; + max-width: 200px; + text-decoration: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.twipsy-arrow { + position: absolute; + width: 0; + height: 0; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1000; + padding: 5px; + display: none; +} +.popover.above .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.popover.below .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.popover .arrow { + position: absolute; + width: 0; + height: 0; +} +.popover .inner { + background: #000000; + background: rgba(0, 0, 0, 0.8); + padding: 3px; + overflow: hidden; + width: 280px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +} +.popover .title { + background-color: #f5f5f5; + padding: 9px 15px; + line-height: 1; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + border-bottom: 1px solid #eee; +} +.popover .content { + background-color: #ffffff; + padding: 14px; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.popover .content p, .popover .content ul, .popover .content ol { + margin-bottom: 0; +} +.fade { + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + opacity: 0; +} +.fade.in { + opacity: 1; +} +.label { + padding: 1px 3px 2px; + font-size: 9.75px; + font-weight: bold; + color: #ffffff; + text-transform: uppercase; + white-space: nowrap; + background-color: #bfbfbf; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + text-shadow: none; +} +.label.important { + background-color: #c43c35; +} +.label.warning { + background-color: #f89406; +} +.label.success { + background-color: #46a546; +} +.label.notice { + background-color: #62cffc; +} +.media-grid { + margin-left: -20px; + margin-bottom: 0; + zoom: 1; +} +.media-grid:before, .media-grid:after { + display: table; + content: ""; + zoom: 1; +} +.media-grid:after { + clear: both; +} +.media-grid li { + display: inline; +} +.media-grid a { + float: left; + padding: 4px; + margin: 0 0 18px 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); +} +.media-grid a img { + display: block; +} +.media-grid a:hover { + border-color: #0069d6; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} \ No newline at end of file diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.min.css b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000000..140f731dfa --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.2.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media .pull-left{margin-right:10px}.media .pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings-white.png b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000..3bf6484a29 Binary files /dev/null and b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings-white.png differ diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings.png b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings.png new file mode 100644 index 0000000000..a996999320 Binary files /dev/null and b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/img/glyphicons-halflings.png differ diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/js/bootstrap.js b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/js/bootstrap.js new file mode 100644 index 0000000000..6c15a58329 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/flightjs-example-app/components/bootstrap/js/bootstrap.js @@ -0,0 +1,2159 @@ +/* =================================================== + * bootstrap-transition.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + , name + + for (name in transEndEventNames){ + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-alert.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.jQuery);/* ============================================================ + * bootstrap-button.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-carousel.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , to: function (pos) { + var $active = this.$element.find('.item.active') + , children = $active.parent().children() + , activePos = children.index($active) + , that = this + + if (pos > (children.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activePos == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) + } + + , pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle() + } + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0] + }) + + if ($next.hasClass('active')) return + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + , pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + $target.carousel(options) + e.preventDefault() + }) + +}(window.jQuery);/* ============================================================= + * bootstrap-collapse.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + } + + , hide: function () { + var dimension + if (this.transitioning) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + } + + , reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + } + + , transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = typeof option == 'object' && option + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.jQuery);/* ============================================================ + * bootstrap-dropdown.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + $parent.toggleClass('open') + } + + $this.focus() + + return false + } + + , keydown: function (e) { + var $this + , $items + , $active + , $parent + , isActive + , index + + if (!/(38|40|27)/.test(e.keyCode)) return + + $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + if (!isActive || (isActive && e.keyCode == 27)) return $this.click() + + $items = $('[role=menu] li:not(.divider):visible a', $parent) + + if (!$items.length) return + + index = $items.index($items.filter(':focus')) + + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items + .eq(index) + .focus() + } + + } + + function clearMenus() { + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) + } + + function getParent($this) { + var selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + $parent.length || ($parent = $this.parent()) + + return $parent + } + + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.dropdown + + $.fn.dropdown = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + /* DROPDOWN NO CONFLICT + * ==================== */ + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + $(document) + .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) + .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('touchstart.dropdown.data-api', '.dropdown-menu', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + +}(window.jQuery);/* ========================================================= + * bootstrap-modal.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#modals + * ========================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* MODAL CLASS DEFINITION + * ====================== */ + + var Modal = function (element, options) { + this.options = options + this.$element = $(element) + .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) + this.options.remote && this.$element.find('.modal-body').load(this.options.remote) + } + + Modal.prototype = { + + constructor: Modal + + , toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + , e = $.Event('show') + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.escape() + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(document.body) //don't move modals dom position + } + + that.$element + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element + .addClass('in') + .attr('aria-hidden', false) + + that.enforceFocus() + + transition ? + that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) : + that.$element.focus().trigger('shown') + + }) + } + + , hide: function (e) { + e && e.preventDefault() + + var that = this + + e = $.Event('hide') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + + $(document).off('focusin.modal') + + this.$element + .removeClass('in') + .attr('aria-hidden', true) + + $.support.transition && this.$element.hasClass('fade') ? + this.hideWithTransition() : + this.hideModal() + } + + , enforceFocus: function () { + var that = this + $(document).on('focusin.modal', function (e) { + if (that.$element[0] !== e.target && !that.$element.has(e.target).length) { + that.$element.focus() + } + }) + } + + , escape: function () { + var that = this + if (this.isShown && this.options.keyboard) { + this.$element.on('keyup.dismiss.modal', function ( e ) { + e.which == 27 && that.hide() + }) + } else if (!this.isShown) { + this.$element.off('keyup.dismiss.modal') + } + } + + , hideWithTransition: function () { + var that = this + , timeout = setTimeout(function () { + that.$element.off($.support.transition.end) + that.hideModal() + }, 500) + + this.$element.one($.support.transition.end, function () { + clearTimeout(timeout) + that.hideModal() + }) + } + + , hideModal: function (that) { + this.$element + .hide() + .trigger('hidden') + + this.backdrop() + } + + , removeBackdrop: function () { + this.$backdrop.remove() + this.$backdrop = null + } + + , backdrop: function (callback) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('