summaryrefslogtreecommitdiffstats
path: root/third_party/webkit/PerformanceTests/MotionMark/resources
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webkit/PerformanceTests/MotionMark/resources')
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.css774
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/animometer.js703
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/graph.js615
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/debug-runner/tests.js345
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/extensions.js670
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css520
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js626
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js179
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg92
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg26
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg26
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js81
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/statistics.js397
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/resources/strings.js51
14 files changed, 5105 insertions, 0 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg viewBox="0 0 1000 1000" preserveAspectRatio="none" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <g fill="white" stroke="white" stroke-width="0.15">
+ <path fill-opacity="1" stroke-opacity="1" d=" M 0 0 L 327.88 0 C 325.14 2.87 322.60 5.94 319.73 8.68 C 315.84 12.50 311.31 16.05 309.30 21.31 C 303.10 37.43 296.87 53.54 290.57 69.62 C 288.47 75.11 285.91 80.43 284.24 86.07 C 285.81 87.43 287.37 88.81 289.07 90.01 C 311.23 105.31 332.96 121.25 355.21 136.43 C 357.15 140.82 359.76 145.01 360.61 149.80 C 361.24 153.54 361.64 157.34 361.37 161.13 C 358.55 166.08 356.04 171.21 353.27 176.19 C 353.07 176.54 352.67 177.23 352.48 177.57 C 350 179.82 347.14 181.57 344.29 183.30 C 335.73 188.47 327.27 193.80 318.71 198.98 C 308.13 198.76 297.56 199.12 287.01 199.74 C 279.65 200.20 272.27 199.53 264.92 200.02 C 262.30 200.09 259.91 201.30 257.93 202.94 C 238.82 218.89 219.07 234.08 199.86 249.90 C 196.40 252.94 194.22 257.05 191.56 260.74 C 185.35 267.44 176.30 270.51 169.90 276.91 C 167.71 282.16 169.92 288.14 170.35 293.60 C 171.49 300.35 172.29 307.14 173.21 313.92 C 173.56 316.94 174.94 319.79 177.25 321.80 C 191.06 333.94 203.32 347.74 217.23 359.78 C 225.25 367.81 233.44 375.66 241.21 383.92 C 240.08 390.20 237.63 396.53 238.91 402.98 C 243.04 426.95 247.04 450.94 251.10 474.92 C 252.01 480.25 253.09 485.59 253.21 491.02 C 252.78 493.08 252.36 495.16 251.80 497.20 C 245.46 503.93 239.30 510.88 232.53 517.18 C 229.17 519.86 225.15 522.50 223.72 526.76 C 222.48 536.86 222.68 547.08 221.69 557.21 C 221.55 562.43 220.62 567.83 222.17 572.93 C 227.92 589.76 231.93 607.12 236.76 624.23 C 237.77 628.08 239 631.89 239.78 635.81 C 236.34 648.91 232.70 661.96 229.12 675.02 C 221.78 676.32 214.41 674.68 207.03 674.87 C 197.35 675.08 187.73 673.63 178.06 673.91 C 167.70 674.16 157.40 672.47 147.04 672.92 C 134.73 673.25 122.45 671.07 110.15 672.14 C 114.51 679.54 119.71 686.40 124.41 693.59 C 143.51 722.45 162.87 751.15 181.98 780 C 185.26 784.93 191.47 785.96 196.30 788.75 C 197.35 794.78 196.74 800.90 196.84 806.98 C 196.94 817.65 196.93 828.31 196.97 838.98 C 197.12 846.82 196.23 854.78 198.23 862.46 C 198.18 870.99 198.91 879.57 197.90 888.06 C 196.92 891.68 197.94 895.32 199.28 898.70 C 195.30 904.88 190.33 910.34 185.64 915.99 C 178.89 920.62 171.57 924.35 164.65 928.72 C 158.28 932.76 151.41 936 145.28 940.39 C 140 944.77 136.22 950.60 131.64 955.65 C 128.24 959.88 124.34 963.73 121.19 968.16 C 119.32 970.80 120.37 974.22 120.59 977.20 C 121.77 984.78 122.70 992.40 123.77 1000 L 0 1000 L 0 0 Z"/>
+ <path fill-opacity="0.9883" stroke-opacity="0.9883" d=" M 169.90 276.91 C 176.30 270.51 185.35 267.44 191.56 260.74 C 195.63 265.49 201.89 267.02 207.24 269.80 C 229.32 280.67 251.38 291.56 273.44 302.46 C 289.29 309.67 304.43 318.39 320.48 325.16 C 323.79 331.38 327.72 337.24 331.27 343.31 C 301.44 357.25 271.05 370 241.21 383.92 C 233.44 375.66 225.25 367.81 217.23 359.78 C 203.32 347.74 191.06 333.94 177.25 321.80 C 174.94 319.79 173.56 316.94 173.21 313.92 C 172.29 307.14 171.49 300.35 170.35 293.60 C 169.92 288.14 167.71 282.16 169.90 276.91 Z"/>
+ <path fill-opacity="0.9804" stroke-opacity="0.9804" d=" M 110.15 672.14 C 122.45 671.07 134.73 673.25 147.04 672.92 C 157.40 672.47 167.70 674.16 178.06 673.91 C 187.73 673.63 197.35 675.08 207.03 674.87 C 214.41 674.68 221.78 676.32 229.12 675.02 C 230.32 677.25 231.56 679.45 232.90 681.60 C 233.20 683.35 233.22 685.15 232.89 686.92 C 226.83 717.17 221.18 747.50 215.10 777.75 C 209.29 781.47 203.40 785.09 197.76 789.07 C 197.63 813.54 198.62 838 198.23 862.46 C 196.23 854.78 197.12 846.82 196.97 838.98 C 196.93 828.31 196.94 817.65 196.84 806.98 C 196.74 800.90 197.35 794.78 196.30 788.75 C 191.47 785.96 185.26 784.93 181.98 780 C 162.87 751.15 143.51 722.45 124.41 693.59 C 119.71 686.40 114.51 679.54 110.15 672.14 Z"/>
+ <path fill-opacity="0.9687" stroke-opacity="0.9687" d=" M 287.01 199.74 C 297.56 199.12 308.13 198.76 318.71 198.98 C 320.17 228.28 318.86 257.66 320.23 286.97 C 320.34 299.70 320.40 312.43 320.48 325.16 C 304.43 318.39 289.29 309.67 273.44 302.46 C 251.38 291.56 229.32 280.67 207.24 269.80 C 201.89 267.02 195.63 265.49 191.56 260.74 C 194.22 257.05 196.40 252.94 199.86 249.90 C 219.07 234.08 238.82 218.89 257.93 202.94 C 259.91 201.30 262.30 200.09 264.92 200.02 C 272.27 199.53 279.65 200.20 287.01 199.74 Z"/>
+ <path fill-opacity="0.953" stroke-opacity="0.953" d=" M 327.88 0 L 373.98 0 C 367.79 45.48 361.61 90.97 355.21 136.43 C 332.96 121.25 311.23 105.31 289.07 90.01 C 287.37 88.81 285.81 87.43 284.24 86.07 C 285.91 80.43 288.47 75.11 290.57 69.62 C 296.87 53.54 303.10 37.43 309.30 21.31 C 311.31 16.05 315.84 12.50 319.73 8.68 C 322.60 5.94 325.14 2.87 327.88 0 Z"/>
+ <path fill-opacity="0.9491" stroke-opacity="0.9491" d=" M 164.65 928.72 C 171.57 924.35 178.89 920.62 185.64 915.99 C 186.75 944 188.72 971.99 190.07 1000 L 123.77 1000 C 122.70 992.40 121.77 984.78 120.59 977.20 C 120.37 974.22 119.32 970.80 121.19 968.16 C 124.34 963.73 128.24 959.88 131.64 955.65 C 136.22 950.60 140 944.77 145.28 940.39 C 151.41 936 158.28 932.76 164.65 928.72 Z"/>
+ <path fill-opacity="0.9295" stroke-opacity="0.9295" d=" M 331.27 343.31 C 342.73 349.21 354.49 354.50 365.86 360.56 C 366.36 361.84 366.86 363.12 367.37 364.41 C 367.21 366.77 366.28 368.98 365.20 371.06 C 362.81 375.78 360.53 380.54 358.35 385.36 C 345.47 397.11 333.54 409.87 321.09 422.06 C 299.90 443.25 278.73 464.47 257.50 485.61 C 255.90 487.27 254.44 489.06 253.21 491.02 C 253.09 485.59 252.01 480.25 251.10 474.92 C 247.04 450.94 243.04 426.95 238.91 402.98 C 237.63 396.53 240.08 390.20 241.21 383.92 C 271.05 370 301.44 357.25 331.27 343.31 Z"/>
+ <path fill-opacity="0.8785" stroke-opacity="0.8785" d=" M 223.72 526.76 C 225.15 522.50 229.17 519.86 232.53 517.18 C 238.93 523.27 246.16 528.39 253.01 533.95 C 280.84 556.11 308.83 578.09 336.63 600.29 C 341.10 603.79 346.07 606.93 349.22 611.79 C 350.70 615.38 352.13 618.98 353.74 622.52 C 347.24 625.52 339.96 624.93 333.04 625.88 C 301.97 629.40 270.82 632.13 239.78 635.81 C 239 631.89 237.77 628.08 236.76 624.23 C 231.93 607.12 227.92 589.76 222.17 572.93 C 220.62 567.83 221.55 562.43 221.69 557.21 C 222.68 547.08 222.48 536.86 223.72 526.76 Z"/>
+ <path fill-opacity="0.8746" stroke-opacity="0.8746" d=" M 199.28 898.70 C 203.46 901.06 207.86 902.98 212.33 904.76 C 214.88 905.73 217.17 907.37 218.69 909.68 C 225.30 927.02 231.55 944.50 238.11 961.86 C 239.21 964.87 240.62 967.82 241.15 971.02 C 241.25 973.62 240.44 976.14 239.87 978.66 C 238.03 985.74 236.68 992.94 234.74 1000 L 190.07 1000 C 188.72 971.99 186.75 944 185.64 915.99 C 190.33 910.34 195.30 904.88 199.28 898.70 Z"/>
+ <path fill-opacity="0.8706" stroke-opacity="0.8706" d=" M 232.90 681.60 C 235.14 683.02 237.58 684.12 240.11 684.93 C 258.41 690.06 276.85 694.79 294.93 700.68 C 304.80 726.80 314.30 753.06 323.99 779.25 C 321.69 780.75 319.57 782.51 317.43 784.23 C 283.33 781.96 249.22 779.81 215.10 777.75 C 221.18 747.50 226.83 717.17 232.89 686.92 C 233.22 685.15 233.20 683.35 232.90 681.60 Z"/>
+ <path fill-opacity="0.8589" stroke-opacity="0.8589" d=" M 353.74 622.52 C 354.67 624.51 355 626.71 354.72 628.90 C 354.14 631.20 353.60 633.50 353.05 635.80 C 350.68 639.43 347.58 642.48 344.71 645.70 C 328.13 664.04 311.35 682.20 294.93 700.68 C 276.85 694.79 258.41 690.06 240.11 684.93 C 237.58 684.12 235.14 683.02 232.90 681.60 C 231.56 679.45 230.32 677.25 229.12 675.02 C 232.70 661.96 236.34 648.91 239.78 635.81 C 270.82 632.13 301.97 629.40 333.04 625.88 C 339.96 624.93 347.24 625.52 353.74 622.52 Z"/>
+ <path fill-opacity="0.855" stroke-opacity="0.855" d=" M 197.76 789.07 C 203.40 785.09 209.29 781.47 215.10 777.75 C 249.22 779.81 283.33 781.96 317.43 784.23 C 315.73 791.84 313.84 799.40 312.11 807 C 310.31 810.16 307.51 812.57 304.47 814.49 C 287.18 825.78 270.27 837.63 253.03 848.98 C 236.55 859.79 220.52 871.26 203.96 881.93 C 201.52 883.50 199.47 885.61 197.90 888.06 C 198.91 879.57 198.18 870.99 198.23 862.46 C 198.62 838 197.63 813.54 197.76 789.07 Z"/>
+ <path fill-opacity="0.855" stroke-opacity="0.855" d=" M 344.29 183.30 C 347.14 181.57 350 179.82 352.48 177.57 C 352.77 181.76 355.26 185.30 357.10 188.94 C 365.30 204.47 373.30 220.10 381.52 235.62 C 383.12 238.45 384.06 241.61 384.44 244.84 C 387.81 271.89 391.59 298.89 394.85 325.96 C 385.10 337.41 375.36 348.89 365.86 360.56 C 354.49 354.50 342.73 349.21 331.27 343.31 C 327.72 337.24 323.79 331.38 320.48 325.16 C 320.40 312.43 320.34 299.70 320.23 286.97 C 318.86 257.66 320.17 228.28 318.71 198.98 C 327.27 193.80 335.73 188.47 344.29 183.30 Z"/>
+ <path fill-opacity="0.8432" stroke-opacity="0.8432" d=" M 321.09 422.06 C 333.54 409.87 345.47 397.11 358.35 385.36 C 358.79 393.90 358 402.41 357.61 410.93 C 357.58 424.29 356.35 437.61 356.32 450.97 C 355.30 462.60 355.77 474.29 354.82 485.93 C 354.49 491.91 354.57 497.91 354.23 503.90 C 350.84 504.27 347.41 504.51 344.01 504.17 C 313.30 501.45 282.48 500.24 251.80 497.20 C 252.36 495.16 252.78 493.08 253.21 491.02 C 254.44 489.06 255.90 487.27 257.50 485.61 C 278.73 464.47 299.90 443.25 321.09 422.06 Z"/>
+ <path fill-opacity="0.8393" stroke-opacity="0.8393" d=" M 373.98 0 L 375.50 0 C 397.90 16.47 420.67 32.46 443.14 48.85 C 449.83 53.79 456.77 58.38 463.25 63.61 C 431.93 89.13 400.82 114.91 369.61 140.56 C 366.28 143.28 362.37 145.67 360.61 149.80 C 359.76 145.01 357.15 140.82 355.21 136.43 C 361.61 90.97 367.79 45.48 373.98 0 Z"/>
+ <path fill-opacity="0.8275" stroke-opacity="0.8275" d=" M 251.80 497.20 C 282.48 500.24 313.30 501.45 344.01 504.17 C 347.41 504.51 350.84 504.27 354.23 503.90 C 357.03 506.62 361.90 508.29 361.97 512.80 C 358.05 541.20 353.99 569.58 349.99 597.97 C 349.44 602.54 347.90 607.21 349.22 611.79 C 346.07 606.93 341.10 603.79 336.63 600.29 C 308.83 578.09 280.84 556.11 253.01 533.95 C 246.16 528.39 238.93 523.27 232.53 517.18 C 239.30 510.88 245.46 503.93 251.80 497.20 Z"/>
+ <path fill-opacity="0.8197" stroke-opacity="0.8197" d=" M 304.47 814.49 C 307.51 812.57 310.31 810.16 312.11 807 C 310.99 813.29 311.73 819.70 311.72 826.05 C 312.47 837.02 312.51 848.02 312.50 859.01 C 300.69 875.28 289.35 891.88 277.41 908.05 C 270.37 909.81 263.17 908.36 256.04 908.19 C 249.68 907.96 243.30 908.12 236.94 907.87 C 231.21 907.71 225.49 906.94 219.75 907.36 C 219.49 907.94 218.96 909.10 218.69 909.68 C 217.17 907.37 214.88 905.73 212.33 904.76 C 207.86 902.98 203.46 901.06 199.28 898.70 C 197.94 895.32 196.92 891.68 197.90 888.06 C 199.47 885.61 201.52 883.50 203.96 881.93 C 220.52 871.26 236.55 859.79 253.03 848.98 C 270.27 837.63 287.18 825.78 304.47 814.49 Z"/>
+ <path fill-opacity="0.7844" stroke-opacity="0.7844" d=" M 219.75 907.36 C 225.49 906.94 231.21 907.71 236.94 907.87 C 243.30 908.12 249.68 907.96 256.04 908.19 C 263.17 908.36 270.37 909.81 277.41 908.05 C 279.98 912.58 284.54 915.31 288.41 918.60 C 295.15 924.19 301.91 929.75 308.65 935.35 C 313.06 939.14 318.10 942.31 321.57 947.09 C 318.07 952.97 314.74 958.95 311.43 964.94 C 302.10 970.37 292.91 976.03 283.57 981.44 C 281.17 982.96 278.31 984.13 276.66 986.54 C 275.16 990.86 275.11 995.50 274.48 1000 L 234.74 1000 C 236.68 992.94 238.03 985.74 239.87 978.66 C 240.44 976.14 241.25 973.62 241.15 971.02 C 240.62 967.82 239.21 964.87 238.11 961.86 C 231.55 944.50 225.30 927.02 218.69 909.68 C 218.96 909.10 219.49 907.94 219.75 907.36 Z"/>
+ <path fill-opacity="0.7687" stroke-opacity="0.7687" d=" M 375.50 0 L 548.99 0 C 548.07 11.56 546.25 23.02 544.95 34.54 C 525.98 45.47 506.58 55.63 487.69 66.69 C 479.58 65.38 471.41 64.56 463.25 63.61 C 456.77 58.38 449.83 53.79 443.14 48.85 C 420.67 32.46 397.90 16.47 375.50 0 Z"/>
+ <path fill-opacity="0.7569" stroke-opacity="0.7569" d=" M 352.48 177.57 C 352.67 177.23 353.07 176.54 353.27 176.19 C 355.78 178.93 358.62 181.38 361.89 183.17 C 373.79 190.05 384.67 198.48 396.38 205.65 C 405.55 211.85 415.12 217.43 424.07 223.95 C 435.96 231.69 447.97 239.23 459.67 247.26 C 464.57 250.45 469.33 253.97 474.82 256.12 C 481.80 259.13 489.74 260.31 495.64 265.43 C 491.08 270.99 486.53 276.57 481.84 282.02 C 453.09 297.13 423.63 310.91 394.85 325.96 C 391.59 298.89 387.81 271.89 384.44 244.84 C 384.06 241.61 383.12 238.45 381.52 235.62 C 373.30 220.10 365.30 204.47 357.10 188.94 C 355.26 185.30 352.77 181.76 352.48 177.57 Z"/>
+ <path fill-opacity="0.753" stroke-opacity="0.753" d=" M 369.61 140.56 C 400.82 114.91 431.93 89.13 463.25 63.61 C 471.41 64.56 479.58 65.38 487.69 66.69 C 486.82 82.73 485.05 98.72 483.75 114.73 C 483.15 119.05 483.64 123.99 480.54 127.48 C 469.52 141.36 458.63 155.35 447.54 169.17 C 426.29 167.96 405.18 164.93 383.98 162.95 C 376.44 162.39 368.97 160.61 361.37 161.13 C 361.64 157.34 361.24 153.54 360.61 149.80 C 362.37 145.67 366.28 143.28 369.61 140.56 Z"/>
+ <path fill-opacity="0.7491" stroke-opacity="0.7491" d=" M 344.71 645.70 C 347.58 642.48 350.68 639.43 353.05 635.80 C 353.70 641.86 356.06 647.52 357.70 653.34 C 367.82 686.89 378.38 720.31 388.25 753.93 C 381.61 761.08 375.26 768.49 368.57 775.58 C 353.73 777.09 338.83 777.79 323.99 779.25 C 314.30 753.06 304.80 726.80 294.93 700.68 C 311.35 682.20 328.13 664.04 344.71 645.70 Z"/>
+ <path fill-opacity="0.7491" stroke-opacity="0.7491" d=" M 367.37 364.41 C 368.87 366.30 370.70 367.89 372.63 369.33 C 379.75 374.55 386.90 379.73 394 384.98 C 396.46 386.66 397.68 389.46 398.65 392.18 C 409.39 422.55 420.71 452.72 431.53 483.07 C 430.70 484.02 429.91 485 429.06 485.94 C 421.71 492.88 414.29 499.73 407.01 506.74 C 393.67 507.87 380.29 508.51 366.96 509.77 C 364.79 509.76 362.96 510.89 361.97 512.80 C 361.90 508.29 357.03 506.62 354.23 503.90 C 354.57 497.91 354.49 491.91 354.82 485.93 C 355.77 474.29 355.30 462.60 356.32 450.97 C 356.35 437.61 357.58 424.29 357.61 410.93 C 358 402.41 358.79 393.90 358.35 385.36 C 360.53 380.54 362.81 375.78 365.20 371.06 C 366.28 368.98 367.21 366.77 367.37 364.41 Z"/>
+ <path fill-opacity="0.7451" stroke-opacity="0.7451" d=" M 361.37 161.13 C 368.97 160.61 376.44 162.39 383.98 162.95 C 405.18 164.93 426.29 167.96 447.54 169.17 C 456.58 182.09 466.70 194.20 476.10 206.86 C 488.03 222.59 500.24 238.11 512.07 253.92 C 506.49 257.58 500.73 261.09 495.64 265.43 C 489.74 260.31 481.80 259.13 474.82 256.12 C 469.33 253.97 464.57 250.45 459.67 247.26 C 447.97 239.23 435.96 231.69 424.07 223.95 C 415.12 217.43 405.55 211.85 396.38 205.65 C 384.67 198.48 373.79 190.05 361.89 183.17 C 358.62 181.38 355.78 178.93 353.27 176.19 C 356.04 171.21 358.55 166.08 361.37 161.13 Z"/>
+ <path fill-opacity="0.7334" stroke-opacity="0.7334" d=" M 283.57 981.44 C 292.91 976.03 302.10 970.37 311.43 964.94 C 311.57 976.62 311.48 988.31 311.52 1000 L 274.48 1000 C 275.11 995.50 275.16 990.86 276.66 986.54 C 278.31 984.13 281.17 982.96 283.57 981.44 Z"/>
+ <path fill-opacity="0.702" stroke-opacity="0.702" d=" M 366.96 509.77 C 380.29 508.51 393.67 507.87 407.01 506.74 C 415.89 532.41 425.55 557.83 433.99 583.64 C 427.09 595.62 420.28 607.64 413.32 619.59 C 395.24 621.90 377.04 623.19 358.94 625.21 C 356.73 625.22 355.69 627.25 354.72 628.90 C 355 626.71 354.67 624.51 353.74 622.52 C 352.13 618.98 350.70 615.38 349.22 611.79 C 347.90 607.21 349.44 602.54 349.99 597.97 C 353.99 569.58 358.05 541.20 361.97 512.80 C 362.96 510.89 364.79 509.76 366.96 509.77 Z"/>
+ <path fill-opacity="0.6942" stroke-opacity="0.6942" d=" M 312.50 859.01 C 318.79 860.71 324.36 864.19 330.34 866.66 C 340.54 871.48 351.13 875.47 361.11 880.75 C 368.34 888.78 374.93 897.37 382.12 905.45 C 382.47 918.41 383.24 931.35 383.76 944.30 C 383.10 944.93 382.45 945.58 381.81 946.23 C 365.22 945.99 348.63 946.36 332.05 946.01 C 328.52 945.92 325.03 946.45 321.57 947.09 C 318.10 942.31 313.06 939.14 308.65 935.35 C 301.91 929.75 295.15 924.19 288.41 918.60 C 284.54 915.31 279.98 912.58 277.41 908.05 C 289.35 891.88 300.69 875.28 312.50 859.01 Z"/>
+ <path fill-opacity="0.6746" stroke-opacity="0.6746" d=" M 323.99 779.25 C 338.83 777.79 353.73 777.09 368.57 775.58 C 370.03 778.30 371.42 781.07 373.10 783.67 C 370.01 804.70 367.76 825.84 365.06 846.93 C 363.76 858.20 362.03 869.43 361.11 880.75 C 351.13 875.47 340.54 871.48 330.34 866.66 C 324.36 864.19 318.79 860.71 312.50 859.01 C 312.51 848.02 312.47 837.02 311.72 826.05 C 311.73 819.70 310.99 813.29 312.11 807 C 313.84 799.40 315.73 791.84 317.43 784.23 C 319.57 782.51 321.69 780.75 323.99 779.25 Z"/>
+ <path fill-opacity="0.6589" stroke-opacity="0.6589" d=" M 321.57 947.09 C 325.03 946.45 328.52 945.92 332.05 946.01 C 348.63 946.36 365.22 945.99 381.81 946.23 C 381.69 964.15 381.80 982.08 381.76 1000 L 311.52 1000 C 311.48 988.31 311.57 976.62 311.43 964.94 C 314.74 958.95 318.07 952.97 321.57 947.09 Z"/>
+ <path fill-opacity="0.6314" stroke-opacity="0.6314" d=" M 358.94 625.21 C 377.04 623.19 395.24 621.90 413.32 619.59 C 425.37 632.53 438.16 644.78 450.52 657.44 C 451.82 658.56 451.93 660.27 451.97 661.90 C 447.59 684.96 442.57 707.90 437.80 730.89 C 437.35 732.71 436.78 734.49 436.25 736.30 C 420.39 742.54 404.13 747.73 388.25 753.93 C 378.38 720.31 367.82 686.89 357.70 653.34 C 356.06 647.52 353.70 641.86 353.05 635.80 C 353.60 633.50 354.14 631.20 354.72 628.90 C 355.69 627.25 356.73 625.22 358.94 625.21 Z"/>
+ <path fill-opacity="0.6314" stroke-opacity="0.6314" d=" M 394.85 325.96 C 423.63 310.91 453.09 297.13 481.84 282.02 C 482.68 291.99 484.20 301.89 485.40 311.82 C 488.58 336.52 491.67 361.24 494.97 385.93 C 495.24 388.17 495.36 390.43 495.27 392.70 C 494.98 393.29 494.40 394.47 494.11 395.06 C 462.25 392.21 430.37 389.52 398.47 387.18 C 398.50 388.85 398.54 390.51 398.65 392.18 C 397.68 389.46 396.46 386.66 394 384.98 C 386.90 379.73 379.75 374.55 372.63 369.33 C 370.70 367.89 368.87 366.30 367.37 364.41 C 366.86 363.12 366.36 361.84 365.86 360.56 C 375.36 348.89 385.10 337.41 394.85 325.96 Z"/>
+ <path fill-opacity="0.6314" stroke-opacity="0.6314" d=" M 480.54 127.48 C 483.64 123.99 483.15 119.05 483.75 114.73 C 483.90 118.96 482.75 124.41 486.59 127.38 C 511.90 148.19 537.31 168.90 562.41 189.96 C 550.38 210.51 538.52 231.18 526.52 251.76 C 521.72 252.59 516.86 253.04 512.07 253.92 C 500.24 238.11 488.03 222.59 476.10 206.86 C 466.70 194.20 456.58 182.09 447.54 169.17 C 458.63 155.35 469.52 141.36 480.54 127.48 Z"/>
+ <path fill-opacity="0.6197" stroke-opacity="0.6197" d=" M 373.10 783.67 C 390.18 802.89 407.31 822.08 424.17 841.49 C 410.02 862.72 396.01 884.05 382.12 905.45 C 374.93 897.37 368.34 888.78 361.11 880.75 C 362.03 869.43 363.76 858.20 365.06 846.93 C 367.76 825.84 370.01 804.70 373.10 783.67 Z"/>
+ <path fill-opacity="0.6157" stroke-opacity="0.6157" d=" M 398.47 387.18 C 430.37 389.52 462.25 392.21 494.11 395.06 C 507.28 424.63 520.52 454.18 533.57 483.80 C 528.28 485.95 522.52 485.07 516.98 485.08 C 504.66 484.88 492.32 485.08 480.02 484.26 C 467.69 483.86 455.35 484.30 443.02 483.80 C 438.32 483.76 433.07 482.84 429.06 485.94 C 429.91 485 430.70 484.02 431.53 483.07 C 420.71 452.72 409.39 422.55 398.65 392.18 C 398.54 390.51 398.50 388.85 398.47 387.18 Z"/>
+ <path fill-opacity="0.5844" stroke-opacity="0.5844" d=" M 429.06 485.94 C 433.07 482.84 438.32 483.76 443.02 483.80 C 455.35 484.30 467.69 483.86 480.02 484.26 C 492.32 485.08 504.66 484.88 516.98 485.08 C 522.52 485.07 528.28 485.95 533.57 483.80 C 539.79 490.34 548.27 494.09 555.36 499.59 C 547.53 515.61 539.53 531.54 531.63 547.53 C 524.45 551.24 516.61 553.33 509.10 556.22 C 484.10 565.46 458.83 573.99 433.99 583.64 C 425.55 557.83 415.89 532.41 407.01 506.74 C 414.29 499.73 421.71 492.88 429.06 485.94 Z"/>
+ <path fill-opacity="0.5844" stroke-opacity="0.5844" d=" M 487.69 66.69 C 506.58 55.63 525.98 45.47 544.95 34.54 C 550.76 41.24 556.83 47.69 562.76 54.28 C 565.32 56.80 565.60 60.52 566.26 63.85 C 573.05 98.77 580.17 133.62 586.97 168.53 C 578.90 175.81 570.40 182.60 562.41 189.96 C 537.31 168.90 511.90 148.19 486.59 127.38 C 482.75 124.41 483.90 118.96 483.75 114.73 C 485.05 98.72 486.82 82.73 487.69 66.69 Z"/>
+ <path fill-opacity="0.5216" stroke-opacity="0.5216" d=" M 512.07 253.92 C 516.86 253.04 521.72 252.59 526.52 251.76 C 537.09 261.81 548.06 271.42 558.82 281.26 C 560.14 282.51 561.34 283.91 562.33 285.44 C 569.52 301.98 576.13 318.78 583.48 335.24 C 569.63 344.96 555.01 353.54 540.85 362.81 C 530.10 369.71 519.35 376.60 508.59 383.48 C 504.06 386.41 499.26 389.01 495.27 392.70 C 495.36 390.43 495.24 388.17 494.97 385.93 C 491.67 361.24 488.58 336.52 485.40 311.82 C 484.20 301.89 482.68 291.99 481.84 282.02 C 486.53 276.57 491.08 270.99 495.64 265.43 C 500.73 261.09 506.49 257.58 512.07 253.92 Z"/>
+ <path fill-opacity="0.5138" stroke-opacity="0.5138" d=" M 436.25 736.30 C 436.78 734.49 437.35 732.71 437.80 730.89 C 437.78 732.79 437.53 734.80 438.22 736.64 C 441.14 739 444.70 740.31 448.01 742.02 C 462.68 749.32 477.27 756.77 491.94 764.07 C 498.79 767.56 505.82 770.74 512.43 774.71 C 501.34 792.40 490.14 810.02 479.01 827.69 C 463.85 832.35 448.92 837.79 433.68 842.17 C 430.49 842.09 427.33 841.75 424.17 841.49 C 407.31 822.08 390.18 802.89 373.10 783.67 C 371.42 781.07 370.03 778.30 368.57 775.58 C 375.26 768.49 381.61 761.08 388.25 753.93 C 404.13 747.73 420.39 742.54 436.25 736.30 Z"/>
+ <path fill-opacity="0.502" stroke-opacity="0.502" d=" M 424.17 841.49 C 427.33 841.75 430.49 842.09 433.68 842.17 C 443.79 868.94 454.79 895.37 465.16 922.04 C 460.56 929.15 456.37 936.52 451.83 943.68 C 429.14 944.14 406.45 944.27 383.76 944.30 C 383.24 931.35 382.47 918.41 382.12 905.45 C 396.01 884.05 410.02 862.72 424.17 841.49 Z"/>
+ <path fill-opacity="0.502" stroke-opacity="0.502" d=" M 509.10 556.22 C 516.61 553.33 524.45 551.24 531.63 547.53 C 531.09 554.71 532.47 561.85 532.51 569.03 C 533.82 590.96 534.99 612.90 536.37 634.83 C 536.49 638.03 536.17 641.23 535.71 644.41 C 511.02 648.82 486.33 653.26 461.60 657.44 C 458.13 658.12 453.60 658.08 451.97 661.90 C 451.93 660.27 451.82 658.56 450.52 657.44 C 438.16 644.78 425.37 632.53 413.32 619.59 C 420.28 607.64 427.09 595.62 433.99 583.64 C 458.83 573.99 484.10 565.46 509.10 556.22 Z"/>
+ <path fill-opacity="0.4589" stroke-opacity="0.4589" d=" M 383.76 944.30 C 406.45 944.27 429.14 944.14 451.83 943.68 C 458.08 952.20 465.10 960.12 471.58 968.46 C 473.14 970.27 472.78 972.79 472.87 975.02 C 472.77 983.34 472.82 991.67 472.82 1000 L 381.76 1000 C 381.80 982.08 381.69 964.15 381.81 946.23 C 382.45 945.58 383.10 944.93 383.76 944.30 Z"/>
+ <path fill-opacity="0.451" stroke-opacity="0.451" d=" M 536.37 634.83 C 536.58 638.08 536.48 641.43 537.46 644.58 C 539.62 647.76 543.06 649.85 545.15 653.11 C 545.66 658.17 544.69 663.26 544.85 668.34 C 544.21 689.37 543.11 710.37 542.39 731.40 C 534.92 744.44 528.94 758.25 522.46 771.80 C 519.13 772.81 515.79 773.78 512.43 774.71 C 505.82 770.74 498.79 767.56 491.94 764.07 C 477.27 756.77 462.68 749.32 448.01 742.02 C 444.70 740.31 441.14 739 438.22 736.64 C 437.53 734.80 437.78 732.79 437.80 730.89 C 442.57 707.90 447.59 684.96 451.97 661.90 C 453.60 658.08 458.13 658.12 461.60 657.44 C 486.33 653.26 511.02 648.82 535.71 644.41 C 536.17 641.23 536.49 638.03 536.37 634.83 Z"/>
+ <path fill-opacity="0.4471" stroke-opacity="0.4471" d=" M 583.48 335.24 C 584.46 336.34 585.53 337.35 586.52 338.44 C 588.74 340.41 587.58 343.67 587.71 346.25 C 584.34 395.33 580.99 444.42 577.57 493.49 C 574.88 494.46 572.34 495.77 569.64 496.68 C 564.91 497.79 560.10 498.51 555.36 499.59 C 548.27 494.09 539.79 490.34 533.57 483.80 C 520.52 454.18 507.28 424.63 494.11 395.06 C 494.40 394.47 494.98 393.29 495.27 392.70 C 499.26 389.01 504.06 386.41 508.59 383.48 C 519.35 376.60 530.10 369.71 540.85 362.81 C 555.01 353.54 569.63 344.96 583.48 335.24 Z"/>
+ <path fill-opacity="0.4393" stroke-opacity="0.4393" d=" M 433.68 842.17 C 448.92 837.79 463.85 832.35 479.01 827.69 C 488.83 848.96 499.05 870.04 508.51 891.47 C 493.97 901.52 479.45 911.63 465.16 922.04 C 454.79 895.37 443.79 868.94 433.68 842.17 Z"/>
+ <path fill-opacity="0.3961" stroke-opacity="0.3961" d=" M 548.99 0 L 752.49 0 C 751.57 1.16 751.04 2.54 750.61 3.94 C 750.16 5.19 749.66 6.42 749.13 7.64 C 719.08 25.92 689.52 45.01 659.60 63.50 C 656.73 65.18 653.97 67.02 651.37 69.08 C 655.42 91.72 659.79 114.31 664 136.92 C 664.77 141.83 666.66 146.76 665.62 151.78 C 651.11 157.78 637.30 165.39 622.97 171.81 C 610.97 170.72 598.96 169.67 586.97 168.53 C 580.17 133.62 573.05 98.77 566.26 63.85 C 565.60 60.52 565.32 56.80 562.76 54.28 C 556.83 47.69 550.76 41.24 544.95 34.54 C 546.25 23.02 548.07 11.56 548.99 0 Z"/>
+ <path fill-opacity="0.3687" stroke-opacity="0.3687" d=" M 586.97 168.53 C 598.96 169.67 610.97 170.72 622.97 171.81 C 633.32 193.14 643.74 214.44 653.61 235.98 C 648.65 244.69 642.86 252.90 637.62 261.44 C 617.19 268.02 596.43 273.61 575.89 279.86 C 571.29 281.46 565.79 281.59 562.33 285.44 C 561.34 283.91 560.14 282.51 558.82 281.26 C 548.06 271.42 537.09 261.81 526.52 251.76 C 538.52 231.18 550.38 210.51 562.41 189.96 C 570.40 182.60 578.90 175.81 586.97 168.53 Z"/>
+ <path fill-opacity="0.3412" stroke-opacity="0.3412" d=" M 512.43 774.71 C 515.79 773.78 519.13 772.81 522.46 771.80 C 527.25 776.63 532.88 780.51 538.16 784.78 C 551.94 795.69 565.68 806.65 579.53 817.48 C 583.79 820.92 588.31 824.07 592.20 827.94 C 592.18 829.33 592.15 830.72 592.12 832.13 C 590.98 839.36 589.97 846.61 588.75 853.84 C 575.55 867.75 562.90 882.18 549.54 895.94 C 535.74 896.31 522.21 892.68 508.51 891.47 C 499.05 870.04 488.83 848.96 479.01 827.69 C 490.14 810.02 501.34 792.40 512.43 774.71 Z"/>
+ <path fill-opacity="0.3334" stroke-opacity="0.3334" d=" M 508.51 891.47 C 522.21 892.68 535.74 896.31 549.54 895.94 C 550.96 909.71 554.66 923.17 556.88 936.84 C 557.08 938.56 557.22 940.29 557.38 942.04 C 547.38 951.07 536.31 958.85 526.01 967.53 C 508.78 968.54 491.54 969.34 474.31 970.32 C 473.64 980.19 474.22 990.10 474 1000 L 472.82 1000 C 472.82 991.67 472.77 983.34 472.87 975.02 C 472.78 972.79 473.14 970.27 471.58 968.46 C 465.10 960.12 458.08 952.20 451.83 943.68 C 456.37 936.52 460.56 929.15 465.16 922.04 C 479.45 911.63 493.97 901.52 508.51 891.47 Z"/>
+ <path fill-opacity="0.3216" stroke-opacity="0.3216" d=" M 575.89 279.86 C 596.43 273.61 617.19 268.02 637.62 261.44 C 649.11 279.16 662.99 295.22 674.57 312.89 C 669.49 320.50 664.96 328.47 659.86 336.06 C 653.09 339.62 646.32 343.23 639.31 346.27 C 631.42 347.71 623.67 344.91 615.87 344.16 C 607.08 343.27 598.47 341.13 589.67 340.37 C 588.99 342.32 588.24 344.25 587.71 346.25 C 587.58 343.67 588.74 340.41 586.52 338.44 C 585.53 337.35 584.46 336.34 583.48 335.24 C 576.13 318.78 569.52 301.98 562.33 285.44 C 565.79 281.59 571.29 281.46 575.89 279.86 Z"/>
+ <path fill-opacity="0.3138" stroke-opacity="0.3138" d=" M 589.67 340.37 C 598.47 341.13 607.08 343.27 615.87 344.16 C 623.67 344.91 631.42 347.71 639.31 346.27 C 639.01 352.18 641.28 357.74 642.65 363.39 C 651.70 398.56 660.94 433.68 670.10 468.83 C 671.32 473.15 672.40 477.53 673.10 481.98 C 671.85 483.92 670.76 485.95 669.63 487.95 C 638.97 490.28 608.24 491.42 577.57 493.49 C 580.99 444.42 584.34 395.33 587.71 346.25 C 588.24 344.25 588.99 342.32 589.67 340.37 Z"/>
+ <path fill-opacity="0.3059" stroke-opacity="0.3059" d=" M 474.31 970.32 C 491.54 969.34 508.78 968.54 526.01 967.53 C 528.79 978.42 531.84 989.24 535.09 1000 L 474 1000 C 474.22 990.10 473.64 980.19 474.31 970.32 Z"/>
+ <path fill-opacity="0.302" stroke-opacity="0.302" d=" M 555.36 499.59 C 560.10 498.51 564.91 497.79 569.64 496.68 C 591.15 547.16 611.72 598.03 633.23 648.51 C 632.96 649.01 632.42 650.02 632.14 650.52 C 628.14 651.22 624.08 651.24 620.05 651.15 C 608.68 650.98 597.35 652.06 585.99 652.11 C 572.75 652 559.51 652.48 546.31 653.29 C 546.11 658.33 545.82 663.38 544.85 668.34 C 544.69 663.26 545.66 658.17 545.15 653.11 C 543.06 649.85 539.62 647.76 537.46 644.58 C 536.48 641.43 536.58 638.08 536.37 634.83 C 534.99 612.90 533.82 590.96 532.51 569.03 C 532.47 561.85 531.09 554.71 531.63 547.53 C 539.53 531.54 547.53 515.61 555.36 499.59 Z"/>
+ <path fill-opacity="0.2902" stroke-opacity="0.2902" d=" M 659.60 63.50 C 689.52 45.01 719.08 25.92 749.13 7.64 C 746.17 14.12 744.09 20.95 741.61 27.61 C 726.43 69.59 711.39 111.61 696.08 153.54 C 685.90 153.39 675.80 150.55 665.62 151.78 C 666.66 146.76 664.77 141.83 664 136.92 C 659.79 114.31 655.42 91.72 651.37 69.08 C 653.97 67.02 656.73 65.18 659.60 63.50 Z"/>
+ <path fill-opacity="0.2746" stroke-opacity="0.2746" d=" M 665.62 151.78 C 675.80 150.55 685.90 153.39 696.08 153.54 C 702.53 158.23 709.03 162.85 715.68 167.28 C 717.91 168.86 720.74 170.41 720.95 173.49 C 716.99 189.35 712.80 205.17 708.55 220.96 C 702.71 227.74 695.30 233.01 689.72 240.03 C 694.43 258.79 700.76 277.13 705.65 295.85 C 695.53 301.97 684.56 306.57 674.57 312.89 C 662.99 295.22 649.11 279.16 637.62 261.44 C 642.86 252.90 648.65 244.69 653.61 235.98 C 643.74 214.44 633.32 193.14 622.97 171.81 C 637.30 165.39 651.11 157.78 665.62 151.78 Z"/>
+ <path fill-opacity="0.2667" stroke-opacity="0.2667" d=" M 633.23 648.51 C 636.96 652.72 642.83 653.38 647.86 655.15 C 655.21 657.70 662.83 659.66 669.81 663.16 L 670.43 664.19 C 665.52 670.04 659.35 674.61 653.88 679.89 C 637.25 694.84 621.03 710.27 604.11 724.89 C 602.47 726.05 600.74 727.07 598.95 727.97 C 580.06 728.51 561.27 730.89 542.39 731.40 C 543.11 710.37 544.21 689.37 544.85 668.34 C 545.82 663.38 546.11 658.33 546.31 653.29 C 559.51 652.48 572.75 652 585.99 652.11 C 597.35 652.06 608.68 650.98 620.05 651.15 C 624.08 651.24 628.14 651.22 632.14 650.52 C 632.42 650.02 632.96 649.01 633.23 648.51 Z"/>
+ <path fill-opacity="0.2471" stroke-opacity="0.2471" d=" M 542.39 731.40 C 561.27 730.89 580.06 728.51 598.95 727.97 C 602.54 748.12 605.51 768.37 609.47 788.45 C 611.30 797.84 612.25 807.43 615.07 816.61 C 608.49 819.78 601.98 823.09 595.50 826.47 C 593.13 827.36 592.63 829.94 592.12 832.13 C 592.15 830.72 592.18 829.33 592.20 827.94 C 588.31 824.07 583.79 820.92 579.53 817.48 C 565.68 806.65 551.94 795.69 538.16 784.78 C 532.88 780.51 527.25 776.63 522.46 771.80 C 528.94 758.25 534.92 744.44 542.39 731.40 Z"/>
+ <path fill-opacity="0.2471" stroke-opacity="0.2471" d=" M 556.88 936.84 C 557.66 939.47 558.49 942.39 560.93 944 C 571.58 951.44 582.47 958.56 593.27 965.78 C 596.97 967.84 596.04 972.66 596.15 976.20 C 595.57 984.13 594.99 992.06 594.47 1000 L 535.09 1000 C 531.84 989.24 528.79 978.42 526.01 967.53 C 536.31 958.85 547.38 951.07 557.38 942.04 C 557.22 940.29 557.08 938.56 556.88 936.84 Z"/>
+ <path fill-opacity="0.2393" stroke-opacity="0.2393" d=" M 577.57 493.49 C 608.24 491.42 638.97 490.28 669.63 487.95 C 672.64 492.67 676.16 497.03 679.42 501.58 C 681.82 504.89 682.08 509.10 682.98 512.96 C 686.01 527.26 689.06 541.56 692.18 555.85 C 694.79 566.71 694.12 577.96 695.28 589 C 695.40 597.90 696.86 606.75 696.49 615.66 C 687.62 631.50 678.62 647.28 669.81 663.16 C 662.83 659.66 655.21 657.70 647.86 655.15 C 642.83 653.38 636.96 652.72 633.23 648.51 C 611.72 598.03 591.15 547.16 569.64 496.68 C 572.34 495.77 574.88 494.46 577.57 493.49 Z"/>
+ <path fill-opacity="0.2236" stroke-opacity="0.2236" d=" M 598.95 727.97 C 600.74 727.07 602.47 726.05 604.11 724.89 C 605.28 730.81 609.93 734.93 613.55 739.44 C 619.31 746.36 624.56 753.68 630.34 760.59 C 639.19 771.33 647.40 782.57 656.31 793.26 C 651.21 797.42 646.65 802.22 641.58 806.42 C 632.98 810.38 623.89 813.17 615.07 816.61 C 612.25 807.43 611.30 797.84 609.47 788.45 C 605.51 768.37 602.54 748.12 598.95 727.97 Z"/>
+ <path fill-opacity="0.2236" stroke-opacity="0.2236" d=" M 639.31 346.27 C 646.32 343.23 653.09 339.62 659.86 336.06 C 686.51 356.31 713.55 376.05 740.33 396.14 C 737.83 405.13 735.79 414.24 733.43 423.26 C 726.43 430.99 718.38 437.67 711.03 445.06 C 698.51 457.49 685.27 469.21 673.10 481.98 C 672.40 477.53 671.32 473.15 670.10 468.83 C 660.94 433.68 651.70 398.56 642.65 363.39 C 641.28 357.74 639.01 352.18 639.31 346.27 Z"/>
+ <path fill-opacity="0.204" stroke-opacity="0.204" d=" M 670.43 664.19 C 673.37 669.51 676.64 674.69 680.28 679.57 C 680.07 685.74 678.68 691.78 677.73 697.87 C 672.88 727.26 667.93 756.63 663.09 786.02 C 663.02 789.97 658.96 791.26 656.31 793.26 C 647.40 782.57 639.19 771.33 630.34 760.59 C 624.56 753.68 619.31 746.36 613.55 739.44 C 609.93 734.93 605.28 730.81 604.11 724.89 C 621.03 710.27 637.25 694.84 653.88 679.89 C 659.35 674.61 665.52 670.04 670.43 664.19 Z"/>
+ <path fill-opacity="0.204" stroke-opacity="0.204" d=" M 749.13 7.64 C 749.66 6.42 750.16 5.19 750.61 3.94 C 750.67 6.58 751.26 9.18 752.36 11.59 C 755.89 19.76 759.32 27.98 762.75 36.20 C 764.72 42.32 765.62 48.72 766.93 55.01 C 773.01 86.59 779.53 118.10 785.40 149.72 C 778.91 155.99 772.99 162.83 766.44 169.04 L 765.86 169.66 C 753.56 169.96 741.28 171.12 728.96 170.89 C 726.04 170.77 722.99 171.20 720.95 173.49 C 720.74 170.41 717.91 168.86 715.68 167.28 C 709.03 162.85 702.53 158.23 696.08 153.54 C 711.39 111.61 726.43 69.59 741.61 27.61 C 744.09 20.95 746.17 14.12 749.13 7.64 Z"/>
+ <path fill-opacity="0.1961" stroke-opacity="0.1961" d=" M 549.54 895.94 C 562.90 882.18 575.55 867.75 588.75 853.84 C 611.64 877.83 634.46 901.89 657.15 926.06 C 656.36 929.33 655.59 932.60 654.83 935.87 C 654.19 938.27 652.78 940.46 650.40 941.42 C 633.66 949.65 616.96 957.96 600.28 966.30 C 596.10 967.73 596.74 972.66 596.15 976.20 C 596.04 972.66 596.97 967.84 593.27 965.78 C 582.47 958.56 571.58 951.44 560.93 944 C 558.49 942.39 557.66 939.47 556.88 936.84 C 554.66 923.17 550.96 909.71 549.54 895.94 Z"/>
+ <path fill-opacity="0.1922" stroke-opacity="0.1922" d=" M 689.72 240.03 C 695.30 233.01 702.71 227.74 708.55 220.96 C 729.63 237.23 751.13 252.97 772.39 269.02 C 774.53 273.76 776.69 278.50 778.34 283.45 C 772.10 290.31 765.48 296.90 759.75 304.18 C 758.77 315.38 760.52 326.70 760.51 337.95 C 760.45 347.13 761.52 356.26 761.54 365.43 C 761.72 367.63 760.46 369.50 759.20 371.16 C 752.89 379.47 746.40 387.65 740.33 396.14 C 713.55 376.05 686.51 356.31 659.86 336.06 C 664.96 328.47 669.49 320.50 674.57 312.89 C 684.56 306.57 695.53 301.97 705.65 295.85 C 700.76 277.13 694.43 258.79 689.72 240.03 Z"/>
+ <path fill-opacity="0.1726" stroke-opacity="0.1726" d=" M 728.96 170.89 C 741.28 171.12 753.56 169.96 765.86 169.66 C 767.88 202.79 770.11 235.91 772.39 269.02 C 751.13 252.97 729.63 237.23 708.55 220.96 C 712.80 205.17 716.99 189.35 720.95 173.49 C 722.99 171.20 726.04 170.77 728.96 170.89 Z"/>
+ <path fill-opacity="0.1373" stroke-opacity="0.1373" d=" M 615.07 816.61 C 623.89 813.17 632.98 810.38 641.58 806.42 C 645.25 814.64 651.10 821.57 655.80 829.20 C 662.57 839.43 669.51 849.54 676.01 859.95 C 683.53 871.53 691.70 882.72 698.41 894.81 C 684.54 905.07 670.88 915.62 657.15 926.06 C 634.46 901.89 611.64 877.83 588.75 853.84 C 589.97 846.61 590.98 839.36 592.12 832.13 C 592.63 829.94 593.13 827.36 595.50 826.47 C 601.98 823.09 608.49 819.78 615.07 816.61 Z"/>
+ <path fill-opacity="0.1295" stroke-opacity="0.1295" d=" M 650.40 941.42 C 652.78 940.46 654.19 938.27 654.83 935.87 C 654.11 940.20 656.63 943.95 659.34 947.04 C 659.81 955.51 657.31 963.73 656.19 972.06 C 654.57 981.35 653.10 990.68 651.63 1000 L 594.47 1000 C 594.99 992.06 595.57 984.13 596.15 976.20 C 596.74 972.66 596.10 967.73 600.28 966.30 C 616.96 957.96 633.66 949.65 650.40 941.42 Z"/>
+ <path fill-opacity="0.1099" stroke-opacity="0.1099" d=" M 762.75 36.20 C 766.71 41.26 771.97 45.04 776.93 49.06 C 798.92 67.11 821.26 84.72 843.22 102.80 C 851.79 109.79 860.76 116.35 868.75 124.02 C 863.32 131.42 858.08 138.97 852.75 146.45 C 840.17 147.38 827.57 148.12 814.96 148.25 C 805.13 149.30 795.23 148.69 785.40 149.72 C 779.53 118.10 773.01 86.59 766.93 55.01 C 765.62 48.72 764.72 42.32 762.75 36.20 Z"/>
+ <path fill-opacity="0.1099" stroke-opacity="0.1099" d=" M 765.86 169.66 L 766.44 169.04 C 772.86 175.47 779.26 181.93 786.19 187.83 C 793.68 195.35 801.97 202.02 809.24 209.77 C 815.06 215.97 821.92 221.08 827.75 227.28 C 832.77 232.60 838.67 236.99 843.78 242.23 C 851.02 249.65 858.99 256.30 866.37 263.58 C 867.88 265.06 868.96 266.92 869.91 268.80 C 847.35 272.31 824.78 275.77 802.23 279.32 C 794.26 280.71 786.20 281.51 778.34 283.45 C 776.69 278.50 774.53 273.76 772.39 269.02 C 770.11 235.91 767.88 202.79 765.86 169.66 Z"/>
+ <path fill-opacity="0.0981" stroke-opacity="0.0981" d=" M 659.34 947.04 C 666.64 954.72 675.44 960.72 683.61 967.40 C 686.99 969.43 686.98 973.49 686.86 976.98 C 686.69 984.65 686.91 992.33 686.56 1000 L 651.63 1000 C 653.10 990.68 654.57 981.35 656.19 972.06 C 657.31 963.73 659.81 955.51 659.34 947.04 Z"/>
+ <path fill-opacity="0.0981" stroke-opacity="0.0981" d=" M 680.28 679.57 C 687.62 684.43 696.11 687.13 703.96 691.05 C 722.31 699.32 740.63 707.71 759 715.95 C 762.03 718.58 764.89 721.40 767.81 724.15 C 770.49 726.35 772.43 729.42 771.89 733.04 C 769.33 746.88 766.91 760.75 764.61 774.64 C 764.05 778.01 763.04 781.33 761.34 784.31 C 757.72 790.74 754.18 797.21 750.52 803.62 C 749.47 805.68 747.92 807.89 748.63 810.32 C 750.24 817.07 752.40 823.68 754.30 830.36 C 749.73 838.49 743.41 845.43 738.03 853.02 C 728.16 866.13 718.43 879.35 708.50 892.42 C 705.14 893.21 701.73 893.85 698.41 894.81 C 691.70 882.72 683.53 871.53 676.01 859.95 C 669.51 849.54 662.57 839.43 655.80 829.20 C 651.10 821.57 645.25 814.64 641.58 806.42 C 646.65 802.22 651.21 797.42 656.31 793.26 C 658.96 791.26 663.02 789.97 663.09 786.02 C 667.93 756.63 672.88 727.26 677.73 697.87 C 678.68 691.78 680.07 685.74 680.28 679.57 Z"/>
+ <path fill-opacity="0.0942" stroke-opacity="0.0942" d=" M 752.49 0 L 873.98 0 C 876.68 6.74 879 13.64 881.62 20.41 C 884.17 26.93 884.36 34.01 885.38 40.86 C 888.28 61.72 890.87 82.62 893.89 103.47 C 886.04 110.94 876.82 116.79 868.75 124.02 C 860.76 116.35 851.79 109.79 843.22 102.80 C 821.26 84.72 798.92 67.11 776.93 49.06 C 771.97 45.04 766.71 41.26 762.75 36.20 C 759.32 27.98 755.89 19.76 752.36 11.59 C 751.26 9.18 750.67 6.58 750.61 3.94 C 751.04 2.54 751.57 1.16 752.49 0 Z"/>
+ <path fill-opacity="0.0902" stroke-opacity="0.0902" d=" M 814.96 148.25 C 827.57 148.12 840.17 147.38 852.75 146.45 C 858.94 167.78 866.25 188.79 873.07 209.93 C 878.63 227.75 884.77 245.39 890.20 263.25 C 889.15 265.06 888.17 266.92 887.29 268.81 C 881.49 268.88 875.70 268.56 869.91 268.80 C 868.96 266.92 867.88 265.06 866.37 263.58 C 858.99 256.30 851.02 249.65 843.78 242.23 C 838.67 236.99 832.77 232.60 827.75 227.28 C 821.92 221.08 815.06 215.97 809.24 209.77 C 801.97 202.02 793.68 195.35 786.19 187.83 C 779.26 181.93 772.86 175.47 766.44 169.04 C 772.99 162.83 778.91 155.99 785.40 149.72 C 795.23 148.69 805.13 149.30 814.96 148.25 Z"/>
+ <path fill-opacity="0.0863" stroke-opacity="0.0863" d=" M 711.03 445.06 C 718.38 437.67 726.43 430.99 733.43 423.26 C 738.41 425.93 743.61 428.13 748.88 430.14 C 768.70 438.32 788.46 446.63 808.31 454.74 C 812.63 456.62 817.39 457.76 821.21 460.63 C 822.11 462.68 822.15 464.98 822.32 467.19 C 820.49 484.05 818.56 500.89 816.77 517.75 C 817 524.38 810.75 528.04 808.89 533.89 C 806.01 541.30 802.91 548.62 799.98 556.01 C 797.54 562.18 794.18 568.14 793.58 574.87 C 792.35 587.55 790.89 600.21 789.56 612.88 C 788.95 614.74 788.18 616.55 787.51 618.40 C 777.69 617.60 767.85 616.72 757.99 616.99 C 745.96 617.26 733.99 615.75 721.96 615.93 C 713.46 616.06 704.97 614.27 696.49 615.66 C 696.86 606.75 695.40 597.90 695.28 589 C 694.12 577.96 694.79 566.71 692.18 555.85 C 689.06 541.56 686.01 527.26 682.98 512.96 C 682.08 509.10 681.82 504.89 679.42 501.58 C 676.16 497.03 672.64 492.67 669.63 487.95 C 670.76 485.95 671.85 483.92 673.10 481.98 C 685.27 469.21 698.51 457.49 711.03 445.06 Z"/>
+ <path fill-opacity="0.0746" stroke-opacity="0.0746" d=" M 696.49 615.66 C 704.97 614.27 713.46 616.06 721.96 615.93 C 733.99 615.75 745.96 617.26 757.99 616.99 C 767.85 616.72 777.69 617.60 787.51 618.40 C 777.55 650.78 768.67 683.48 759 715.95 C 740.63 707.71 722.31 699.32 703.96 691.05 C 696.11 687.13 687.62 684.43 680.28 679.57 C 676.64 674.69 673.37 669.51 670.43 664.19 L 669.81 663.16 C 678.62 647.28 687.62 631.50 696.49 615.66 Z"/>
+ <path fill-opacity="0.0746" stroke-opacity="0.0746" d=" M 869.91 268.80 C 875.70 268.56 881.49 268.88 887.29 268.81 C 886.50 273.37 886.89 278.07 885.72 282.57 C 876.65 314.58 867.66 346.61 858.72 378.65 C 857.40 387.68 864.96 395.07 865.78 403.83 C 865.33 406.05 864.08 407.99 863.01 409.95 C 856.26 421.20 850.06 432.78 843.28 444.01 C 837.58 449.10 831.44 453.68 825.64 458.64 C 822.98 460.65 822.73 464.15 822.32 467.19 C 822.15 464.98 822.11 462.68 821.21 460.63 C 817.39 457.76 812.63 456.62 808.31 454.74 C 788.46 446.63 768.70 438.32 748.88 430.14 C 743.61 428.13 738.41 425.93 733.43 423.26 C 735.79 414.24 737.83 405.13 740.33 396.14 C 746.40 387.65 752.89 379.47 759.20 371.16 C 760.46 369.50 761.72 367.63 761.54 365.43 C 761.52 356.26 760.45 347.13 760.51 337.95 C 760.52 326.70 758.77 315.38 759.75 304.18 C 765.48 296.90 772.10 290.31 778.34 283.45 C 786.20 281.51 794.26 280.71 802.23 279.32 C 824.78 275.77 847.35 272.31 869.91 268.80 Z"/>
+ <path fill-opacity="0.0667" stroke-opacity="0.0667" d=" M 698.41 894.81 C 701.73 893.85 705.14 893.21 708.50 892.42 C 713.85 898.11 719.92 903.07 725.25 908.79 C 732.04 916.01 739.89 922.12 746.75 929.26 C 752.61 935.29 758.94 940.86 764.30 947.36 C 758.51 952.88 752.97 958.67 746.93 963.92 C 743.30 967.28 739.36 970.38 736.29 974.28 C 734.56 976.45 734.77 979.39 734.68 982.01 C 734.75 988 734.87 994 734.71 1000 L 686.56 1000 C 686.91 992.33 686.69 984.65 686.86 976.98 C 686.98 973.49 686.99 969.43 683.61 967.40 C 675.44 960.72 666.64 954.72 659.34 947.04 C 656.63 943.95 654.11 940.20 654.83 935.87 C 655.59 932.60 656.36 929.33 657.15 926.06 C 670.88 915.62 684.54 905.07 698.41 894.81 Z"/>
+ <path fill-opacity="0.0471" stroke-opacity="0.0471" d=" M 787.51 618.40 C 788.18 616.55 788.95 614.74 789.56 612.88 C 789.88 614.38 790.15 615.94 790.82 617.36 C 794.07 619.90 798.13 621.09 801.67 623.19 C 805.40 628.31 808.55 633.82 811.83 639.23 C 817.87 649.15 824.12 658.93 830.19 668.84 C 833.45 674.34 837.55 679.47 839.28 685.74 C 836.01 694.64 832.64 703.52 829.63 712.52 C 825.16 716.10 819.26 716.46 813.95 717.96 C 801.60 721.33 789.17 724.40 776.82 727.73 C 774 728.09 772.74 730.65 771.89 733.04 C 772.43 729.42 770.49 726.35 767.81 724.15 C 764.89 721.40 762.03 718.58 759 715.95 C 768.67 683.48 777.55 650.78 787.51 618.40 Z"/>
+ <path fill-opacity="0.0432" stroke-opacity="0.0432" d=" M 754.30 830.36 C 760.41 835.62 767.69 839.19 774.38 843.62 C 793.35 855.31 812.26 867.09 831.20 878.84 C 834.71 881.16 839.88 882.84 840.16 887.80 C 835.77 902.44 832.15 917.30 828.05 932.03 C 826.65 937.67 821.99 941.47 818.08 945.42 C 808.76 946.55 799.37 945.61 790.03 946.14 C 781.47 946.93 772.87 946.89 764.30 947.36 C 758.94 940.86 752.61 935.29 746.75 929.26 C 739.89 922.12 732.04 916.01 725.25 908.79 C 719.92 903.07 713.85 898.11 708.50 892.42 C 718.43 879.35 728.16 866.13 738.03 853.02 C 743.41 845.43 749.73 838.49 754.30 830.36 Z"/>
+ <path fill-opacity="0.0353" stroke-opacity="0.0353" d=" M 808.89 533.89 C 810.75 528.04 817 524.38 816.77 517.75 C 816.73 520.32 817.11 522.87 817.56 525.40 C 832.54 532.40 848.09 538.17 863.22 544.85 C 865.98 545.63 865.90 548.79 866.30 551.10 C 862.94 566.99 860.24 583 856.85 598.88 C 856.09 601.52 854.54 604.04 851.66 604.67 C 838.22 609.05 824.97 613.99 811.60 618.56 C 808.12 619.72 804.84 621.37 801.67 623.19 C 798.13 621.09 794.07 619.90 790.82 617.36 C 790.15 615.94 789.88 614.38 789.56 612.88 C 790.89 600.21 792.35 587.55 793.58 574.87 C 794.18 568.14 797.54 562.18 799.98 556.01 C 802.91 548.62 806.01 541.30 808.89 533.89 Z"/>
+ <path fill-opacity="0.0314" stroke-opacity="0.0314" d=" M 893.89 103.47 C 906.72 109.97 920.98 112.62 934.39 117.61 C 947.25 122.33 960.45 126.10 973.36 130.67 C 974.09 136.90 973.52 143.23 974.75 149.42 C 975.16 156.15 978.35 164.36 973.07 169.95 C 950.88 194.15 929.29 218.90 907.14 243.13 C 901.51 249.85 894.98 255.86 890.20 263.25 C 884.77 245.39 878.63 227.75 873.07 209.93 C 866.25 188.79 858.94 167.78 852.75 146.45 C 858.08 138.97 863.32 131.42 868.75 124.02 C 876.82 116.79 886.04 110.94 893.89 103.47 Z"/>
+ <path fill-opacity="0.0275" stroke-opacity="0.0275" d=" M 790.03 946.14 C 799.37 945.61 808.76 946.55 818.08 945.42 C 817.60 963.61 818.21 981.81 817.75 1000 L 734.71 1000 C 734.87 994 734.75 988 734.68 982.01 C 734.77 979.39 734.56 976.45 736.29 974.28 C 739.36 970.38 743.30 967.28 746.93 963.92 C 752.97 958.67 758.51 952.88 764.30 947.36 C 772.87 946.89 781.47 946.93 790.03 946.14 Z"/>
+ <path fill-opacity="0.0236" stroke-opacity="0.0236" d=" M 873.98 0 L 1000 0 L 1000 103.37 C 993.93 110.15 987.92 117.01 981.22 123.19 C 978.82 125.72 975.31 128.07 975.22 131.91 C 975.04 137.75 975.28 143.60 974.75 149.42 C 973.52 143.23 974.09 136.90 973.36 130.67 C 960.45 126.10 947.25 122.33 934.39 117.61 C 920.98 112.62 906.72 109.97 893.89 103.47 C 890.87 82.62 888.28 61.72 885.38 40.86 C 884.36 34.01 884.17 26.93 881.62 20.41 C 879 13.64 876.68 6.74 873.98 0 Z"/>
+ <path fill-opacity="0.0197" stroke-opacity="0.0197" d=" M 813.95 717.96 C 819.26 716.46 825.16 716.10 829.63 712.52 C 832.23 717.98 837.20 721.57 841.62 725.46 C 855.50 738.57 869.89 751.14 883.88 764.14 C 887.48 767.46 892.20 770.22 893.70 775.19 C 895.08 779.49 895.87 783.95 896.79 788.37 C 897.04 790.36 897.79 792.67 896.47 794.46 C 894.23 797.83 891.15 800.52 888.69 803.72 C 885.29 807.93 883.06 812.88 880.64 817.67 C 871.47 834.90 862.59 852.27 853.59 869.60 C 851.55 873.40 849.91 877.61 846.52 880.46 C 844.06 882.58 841.54 884.78 840.16 887.80 C 839.88 882.84 834.71 881.16 831.20 878.84 C 812.26 867.09 793.35 855.31 774.38 843.62 C 767.69 839.19 760.41 835.62 754.30 830.36 C 752.40 823.68 750.24 817.07 748.63 810.32 C 747.92 807.89 749.47 805.68 750.52 803.62 C 754.18 797.21 757.72 790.74 761.34 784.31 C 763.04 781.33 764.05 778.01 764.61 774.64 C 766.91 760.75 769.33 746.88 771.89 733.04 C 772.74 730.65 774 728.09 776.82 727.73 C 789.17 724.40 801.60 721.33 813.95 717.96 Z"/>
+ <path fill-opacity="0.0197" stroke-opacity="0.0197" d=" M 825.64 458.64 C 831.44 453.68 837.58 449.10 843.28 444.01 C 848.20 449.37 853.71 454.12 859.06 459.03 C 878.31 476.08 896.94 493.83 916.28 510.78 C 920.39 514.58 920.49 520.85 919.86 526.02 C 918.54 530.85 915.41 536.24 910.06 537.19 C 896.89 539.99 883.68 542.68 870.57 545.70 C 867.74 546 866.93 548.78 866.30 551.10 C 865.90 548.79 865.98 545.63 863.22 544.85 C 848.09 538.17 832.54 532.40 817.56 525.40 C 817.11 522.87 816.73 520.32 816.77 517.75 C 818.56 500.89 820.49 484.05 822.32 467.19 C 822.73 464.15 822.98 460.65 825.64 458.64 Z"/>
+ <path fill-opacity="0.0157" stroke-opacity="0.0157" d=" M 851.66 604.67 C 854.54 604.04 856.09 601.52 856.85 598.88 C 856.82 602.45 857.75 606.09 860.32 608.70 C 865.38 614.29 870.41 619.92 875.17 625.79 C 881.34 633.49 888.28 640.56 894.26 648.42 C 892.01 651.58 888.48 653.35 885.26 655.34 C 874.38 662.07 863.58 668.92 852.86 675.89 C 848.21 678.98 842.80 681.24 839.28 685.74 C 837.55 679.47 833.45 674.34 830.19 668.84 C 824.12 658.93 817.87 649.15 811.83 639.23 C 808.55 633.82 805.40 628.31 801.67 623.19 C 804.84 621.37 808.12 619.72 811.60 618.56 C 824.97 613.99 838.22 609.05 851.66 604.67 Z"/>
+ </g>
+</svg>
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg viewBox="0 0 1052 1251" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <g fill-opacity="0.5" fill="white">
+ <polygon points="221.761719 0 223.761719 0 2.12833345 1250.36328 0.128333454 1250.36328"/>
+ <polygon points="261.761719 0 265.761719 0 44.1283335 1250.36328 40.1283335 1250.36328"/>
+ <polygon points="301.761719 0 307.761719 0 86.1283335 1250.36328 80.1283335 1250.36328"/>
+ <polygon points="341.761719 0 349.761719 0 128.128333 1250.36328 120.128333 1250.36328"/>
+ <polygon points="381.761719 0 391.761719 0 170.128333 1250.36328 160.128333 1250.36328"/>
+ <polygon points="421.761719 0 433.761719 0 212.128333 1250.36328 200.128333 1250.36328"/>
+ <polygon points="461.761719 0 475.761719 0 254.128333 1250.36328 240.128333 1250.36328"/>
+ <polygon points="501.761719 0 517.761719 0 296.128333 1250.36328 280.128333 1250.36328"/>
+ <polygon points="541.761719 0 559.761719 0 338.128333 1250.36328 320.128333 1250.36328"/>
+ <polygon points="581.761719 0 601.761719 0 380.128333 1250.36328 360.128333 1250.36328"/>
+ <polygon points="621.761719 0 643.761719 0 422.128333 1250.36328 400.128333 1250.36328"/>
+ <polygon points="661.761719 0 685.761719 0 464.128333 1250.36328 440.128333 1250.36328"/>
+ <polygon points="701.761719 0 727.761719 0 506.128333 1250.36328 480.128333 1250.36328"/>
+ <polygon points="741.761719 0 769.761719 0 548.128333 1250.36328 520.128333 1250.36328"/>
+ <polygon points="781.761719 0 811.761719 0 590.128333 1250.36328 560.128333 1250.36328"/>
+ <polygon points="821.761719 0 853.761719 0 632.128333 1250.36328 600.128333 1250.36328"/>
+ <polygon points="861.761719 0 895.761719 0 674.128333 1250.36328 640.128333 1250.36328"/>
+ <polygon points="901.761719 0 937.761719 0 716.128333 1250.36328 680.128333 1250.36328"/>
+ <polygon points="941.761719 0 979.76172 0 758.128333 1250.36328 720.128333 1250.36328"/>
+ <polygon points="981.76172 0 1021.76172 0 800.128333 1250.36328 760.128333 1250.36328"/>
+ </g>
+</svg>
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <symbol id="root" viewBox="0 0 6882 1698">
+ <path d="M 1314 1681 L 1466 1681 L 1549 1282 C 1555 1254 1566 1229 1582 1205 C 1598 1181 1614 1162 1629 1147 C 1644 1132 1662 1119 1683 1108 C 1704 1097 1729 1092 1758 1092 C 1790 1092 1812 1100 1824 1117 C 1836 1134 1842 1154 1842 1177 C 1842 1197 1840 1219 1835 1241 C 1830 1263 1826 1283 1822 1301 L 1743 1680 L 1895 1680 L 1979 1277 C 1983 1257 1989 1237 2000 1215 C 2010 1193 2024 1173 2040 1155 C 2056 1137 2076 1122 2099 1110 C 2122 1098 2148 1092 2177 1092 C 2197 1092 2213 1095 2225 1101 C 2237 1107 2247 1114 2254 1124 C 2261 1133 2266 1144 2268 1156 C 2270 1168 2271 1180 2271 1191 C 2270 1208 2268 1224 2265 1238 C 2262 1253 2259 1264 2258 1272 L 2173 1680 L 2325 1680 L 2413 1240 C 2416 1228 2418 1213 2420 1197 C 2422 1181 2423 1167 2423 1154 C 2423 1098 2407 1054 2375 1021 C 2343 988 2294 972 2227 972 C 2179 972 2136 984 2098 1007 C 2060 1030 2025 1059 1994 1095 C 1984 1050 1963 1018 1931 1000 C 1899 982 1862 973 1819 973 C 1771 973 1727 983 1686 1004 C 1646 1025 1611 1054 1583 1091 L 1580 1088 L 1600 991 L 1456 991 L 1313 1680 L 1314 1681 Z" fill-opacity="0.6" fill="black"/>
+ <path d="M 2673 1426 C 2690 1410 2711 1399 2736 1391 C 2760 1383 2787 1379 2815 1377 C 2843 1375 2868 1373 2889 1372 C 2906 1370 2923 1367 2941 1363 C 2959 1359 2973 1351 2984 1340 L 2987 1343 C 2982 1376 2974 1407 2965 1436 C 2956 1465 2943 1490 2926 1511 C 2910 1532 2889 1549 2863 1562 C 2838 1574 2806 1581 2769 1581 C 2755 1581 2741 1579 2726 1576 C 2712 1573 2699 1568 2687 1561 C 2675 1554 2666 1545 2658 1534 C 2650 1523 2647 1509 2647 1492 C 2647 1464 2656 1442 2673 1426 L 2673 1426 Z M 3155 1237 L 3155 1237 C 3164 1198 3168 1163 3168 1133 C 3168 1121 3166 1105 3163 1087 C 3159 1069 3149 1051 3133 1034 C 3117 1017 3091 1003 3056 991 C 3021 979 2972 973 2910 973 C 2869 973 2831 977 2795 984 C 2759 992 2727 1004 2698 1023 C 2670 1041 2646 1065 2626 1094 C 2606 1123 2593 1159 2585 1201 L 2729 1201 C 2740 1158 2760 1130 2791 1115 C 2822 1100 2858 1093 2901 1093 C 2932 1093 2959 1099 2982 1110 C 3005 1121 3017 1143 3017 1176 C 3017 1202 3011 1223 2998 1239 C 2985 1255 2965 1265 2937 1266 C 2887 1270 2837 1274 2785 1278 C 2747 1281 2710 1286 2676 1295 C 2641 1304 2611 1318 2584 1336 C 2557 1355 2536 1378 2520 1407 C 2504 1436 2496 1472 2496 1514 C 2496 1544 2502 1571 2513 1594 C 2525 1617 2540 1636 2560 1651 C 2580 1666 2603 1678 2629 1686 C 2655 1694 2682 1698 2710 1698 C 2753 1698 2794 1691 2835 1677 C 2876 1663 2911 1641 2942 1610 C 2944 1637 2953 1658 2970 1674 C 2987 1690 3008 1698 3034 1698 C 3054 1698 3074 1696 3094 1692 C 3114 1688 3133 1684 3153 1679 L 3177 1570 C 3168 1571 3159 1572 3150 1575 C 3141 1577 3132 1578 3123 1578 C 3111 1578 3102 1575 3098 1570 C 3094 1565 3091 1557 3091 1547 C 3091 1537 3093 1527 3096 1515 L 3105 1479 L 3156 1235 L 3155 1237 Z" fill-opacity="0.6" fill="black"/>
+ <path d="M 3232 1681 L 3384 1681 L 3448 1376 C 3455 1341 3465 1308 3477 1277 C 3489 1246 3506 1218 3526 1194 C 3546 1170 3570 1151 3599 1137 C 3628 1123 3662 1116 3701 1116 C 3710 1116 3719 1116 3728 1117 C 3737 1118 3746 1119 3755 1121 L 3787 976 C 3775 974 3762 973 3750 973 C 3738 973 3726 972 3713 972 C 3689 972 3666 977 3644 986 C 3622 995 3602 1007 3583 1022 C 3564 1037 3547 1053 3532 1072 C 3516 1091 3503 1109 3493 1128 L 3490 1125 L 3518 990 L 3374 990 L 3231 1679 L 3232 1681 Z" fill-opacity="0.6" fill="black"/>
+
+ <polygon fill-opacity="0.6" fill="black" points="3726 1681 3878 1681 3927 1446 4044 1346 4166 1681 4334 1681 4166 1245 4470 992 4278 992 3966 1270 3963 1268 4075 729 3923 729"/>
+ <polygon fill-opacity="0.1" fill="black" points="4915 1368 4961 1118 1429 1118 1457 986 6867 986"/>
+
+ <polygon fill="black" points="4930 1298 4976 1048 1444 1048 1472 916 6882 916"/>
+
+ <polygon fill="currentColor" points="1403 263 1257 263 965 1679 1118 1679"/>
+ <polygon fill-opacity="0.8" fill="currentColor" points="1007 263 930 263 639 1679 722 1679"/>
+ <polygon fill-opacity="0.6" fill="currentColor" points="653 263 618 263 326 1679 368 1679"/>
+ <polygon fill-opacity="0.4" fill="currentColor" points="305 263 291 263 0 1679 21 1679"/>
+
+ <path d="M 1466 952 L 1618 952 L 1701 553 C 1707 525 1718 500 1734 476 C 1750 452 1766 433 1781 418 C 1796 403 1814 390 1835 379 C 1856 368 1881 363 1910 363 C 1942 363 1964 371 1976 388 C 1988 405 1994 425 1994 448 C 1994 468 1992 490 1987 512 C 1982 534 1978 554 1974 572 L 1895 951 L 2047 951 L 2131 548 C 2135 528 2141 508 2152 486 C 2162 464 2176 444 2192 426 C 2208 408 2228 393 2251 381 C 2274 369 2300 363 2329 363 C 2349 363 2365 366 2377 372 C 2389 378 2399 385 2406 395 C 2413 404 2418 415 2420 427 C 2422 439 2423 451 2423 462 C 2422 479 2420 495 2417 509 C 2414 524 2411 535 2410 543 L 2325 951 L 2477 951 L 2565 511 C 2568 499 2570 484 2572 468 C 2574 452 2575 438 2575 425 C 2575 369 2559 325 2527 292 C 2495 259 2446 243 2379 243 C 2331 243 2288 255 2250 278 C 2212 301 2177 330 2146 366 C 2136 321 2115 289 2083 271 C 2051 253 2014 244 1971 244 C 1923 244 1879 254 1838 275 C 1798 296 1763 325 1735 362 L 1732 359 L 1752 262 L 1608 262 L 1465 951 L 1466 952 Z" fill="black"/>
+ <path d="M 3180 415 C 3205 449 3218 491 3218 542 C 3218 577 3213 612 3204 649 C 3195 686 3180 719 3161 749 C 3141 779 3117 803 3088 822 C 3059 841 3025 851 2986 851 C 2931 851 2891 834 2865 800 C 2840 766 2827 724 2827 673 C 2827 638 2832 603 2841 566 C 2850 530 2865 496 2884 467 C 2904 437 2928 413 2957 393 C 2986 373 3020 364 3059 364 C 3114 364 3154 381 3180 415 L 3180 415 Z M 3141 938 L 3141 938 C 3189 916 3231 885 3265 847 C 3299 808 3325 763 3343 710 C 3361 658 3370 601 3370 541 C 3370 444 3344 371 3291 320 C 3239 270 3164 245 3068 245 C 3008 245 2954 257 2906 280 C 2858 303 2816 334 2782 373 C 2748 412 2721 457 2703 508 C 2684 559 2675 613 2675 670 C 2675 767 2701 841 2754 893 C 2806 945 2881 971 2977 971 C 3038 971 3093 960 3142 938 L 3141 938 Z" fill="black"/>
+ <path d="M 3620 263 L 3500 263 L 3476 376 L 3596 376 L 3517 753 C 3515 759 3513 770 3511 786 C 3509 802 3508 817 3508 830 C 3508 846 3510 862 3514 877 C 3518 893 3525 906 3535 918 C 3545 930 3559 940 3577 947 C 3595 954 3617 958 3645 958 C 3665 958 3685 957 3708 954 C 3730 951 3751 948 3771 943 L 3796 831 C 3781 835 3766 837 3753 837 C 3739 837 3727 838 3715 838 C 3692 838 3677 833 3670 824 C 3663 815 3660 802 3660 787 C 3660 779 3661 768 3664 755 C 3667 742 3670 727 3673 712 L 3744 375 L 3881 375 L 3905 262 L 3768 262 L 3811 55 L 3663 55 L 3620 262 L 3620 263 Z" fill="black"/>
+ <path d="M 4046 144 L 4197 144 L 4226 0 L 4075 0 L 4046 144 L 4046 144 Z M 3878 952 L 3878 952 L 4030 952 L 4173 263 L 4021 263 L 3878 952 L 3878 952 Z" fill="black"/>
+ <path d="M 4736 415 C 4761 449 4774 491 4774 542 C 4774 577 4769 612 4760 649 C 4751 686 4736 719 4717 749 C 4697 779 4673 803 4644 822 C 4615 841 4581 851 4542 851 C 4487 851 4447 834 4421 800 C 4396 766 4383 724 4383 673 C 4383 638 4388 603 4397 566 C 4406 530 4421 496 4440 467 C 4460 437 4484 413 4513 393 C 4542 373 4576 364 4615 364 C 4670 364 4710 381 4736 415 L 4736 415 Z M 4697 938 L 4697 938 C 4745 916 4787 885 4821 847 C 4855 808 4881 763 4899 710 C 4917 658 4926 601 4926 541 C 4926 444 4900 371 4847 320 C 4795 270 4720 245 4624 245 C 4564 245 4510 257 4462 280 C 4414 303 4372 334 4338 373 C 4304 412 4277 457 4259 508 C 4240 559 4231 613 4231 670 C 4231 767 4257 841 4310 893 C 4362 945 4437 971 4533 971 C 4594 971 4649 960 4698 938 L 4697 938 Z" fill="black"/>
+ <path d="M 4990 952 L 5142 952 L 5219 579 C 5225 551 5235 523 5248 497 C 5261 471 5276 449 5294 431 C 5313 412 5334 397 5357 384 C 5381 371 5407 365 5438 365 C 5466 365 5487 369 5501 377 C 5516 385 5526 395 5532 406 C 5538 417 5542 428 5542 439 C 5542 450 5543 458 5543 464 C 5543 474 5542 484 5540 495 C 5538 506 5535 517 5533 528 L 5445 953 L 5597 953 L 5689 513 C 5692 501 5693 486 5694 470 C 5695 454 5695 440 5695 427 C 5695 371 5679 327 5646 294 C 5614 261 5563 245 5493 245 C 5445 245 5400 256 5359 277 C 5318 298 5283 328 5256 366 L 5253 363 L 5274 263 L 5131 263 L 4988 952 L 4990 952 Z" fill="black"/>
+ </symbol>
+</svg>
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: "<span onclick='benchmarkController.showDebugInfo()'>" + Strings.text.testName + "</span>",
+ text: Strings.text.testName
+ }
+ ],
+ score: [
+ {
+ title: Strings.text.score,
+ text: Strings.json.score
+ }
+ ],
+ details: [
+ {
+ title: "&nbsp;",
+ text: function(data) {
+ var bootstrap = data[Strings.json.complexity][Strings.json.bootstrap];
+ return "<span>±" + (Statistics.largestDeviationPercentage(bootstrap.confidenceLow, bootstrap.median, bootstrap.confidenceHigh) * 100).toFixed(2) + "%</span>";
+ }
+ }
+ ]
+};
+
+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"
+ }
+ }
+};