diff --git a/MotionMark/about.html b/MotionMark/about.html index 0a8ee10..56ae406 100644 --- a/MotionMark/about.html +++ b/MotionMark/about.html @@ -1,5 +1,5 @@ - - - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/bouncing-particles/bouncing-css-images.html b/MotionMark/tests/bouncing-particles/bouncing-css-images.html deleted file mode 100644 index b52a2b9..0000000 --- a/MotionMark/tests/bouncing-particles/bouncing-css-images.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - -
- - - - - - - - - diff --git a/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html b/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html deleted file mode 100644 index 00df8d6..0000000 --- a/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - -
- - - - - - - - - diff --git a/MotionMark/tests/bouncing-particles/bouncing-svg-images.html b/MotionMark/tests/bouncing-particles/bouncing-svg-images.html deleted file mode 100644 index 351cd6b..0000000 --- a/MotionMark/tests/bouncing-particles/bouncing-svg-images.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html b/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html deleted file mode 100644 index 233f649..0000000 --- a/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html b/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html deleted file mode 100644 index fc0e2f9..0000000 --- a/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - -
- - diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js b/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js deleted file mode 100644 index 733f28f..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2015-2023 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingCanvasImage = Utilities.createSubclass(BouncingCanvasParticle, - function(stage) - { - BouncingCanvasParticle.call(this, stage, "image"); - this._imageElement = stage.imageElement; - }, { - - _draw: function() - { - this.context.save(); - this.applyRotation(); - this.context.drawImage(this._imageElement, 0, 0, this.size.x, this.size.y); - this.context.restore(); - } -}); - -BouncingCanvasImagesStage = Utilities.createSubclass(BouncingCanvasParticlesStage, - function() - { - BouncingCanvasParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options); - var imageSrc = options["imageSrc"] || "../resources/yin-yang.svg"; - this.imageElement = document.querySelector(".hidden[src=\"" + imageSrc + "\"]"); - }, - - createParticle: function() - { - return new BouncingCanvasImage(this); - } -}); - -BouncingCanvasImagesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingCanvasImagesStage(), options); - } -); - -window.benchmarkClass = BouncingCanvasImagesBenchmark; - -})(); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js b/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js deleted file mode 100644 index ce12c72..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -BouncingCanvasParticle = Utilities.createSubclass(BouncingParticle, - function(stage, shape) - { - BouncingParticle.call(this, stage); - this.context = stage.context; - this._shape = shape; - this._clip = stage.clip; - }, { - - applyRotation: function() - { - if (this._shape == "circle") - return; - - this.context.translate(this.size.x / 2, this.size.y / 2); - this.context.rotate(this.rotater.degree() * Math.PI / 180); - this.context.translate(-this.size.x / 2, -this.size.y / 2); - }, - - applyClipping: function() - { - var clipPoints = BouncingCanvasParticle.clips[this._clip]; - if (!clipPoints) - return; - - this.context.beginPath(); - clipPoints.forEach(function(point, index) { - var point = this.size.multiply(point); - if (!index) - this.context.moveTo(point.x, point.y); - else - this.context.lineTo(point.x, point.y); - }, this); - - this.context.closePath(); - this.context.clip(); - }, - - _draw: function() - { - throw "Not implemented"; - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this.context.save(); - this.context.translate(this.position.x, this.position.y); - this._draw(); - this.context.restore(); - } -}); - -BouncingCanvasParticle.clips = { - star: [ - new Point(0.50, 0.00), - new Point(0.38, 0.38), - new Point(0.00, 0.38), - new Point(0.30, 0.60), - new Point(0.18, 1.00), - new Point(0.50, 0.75), - new Point(0.82, 1.00), - new Point(0.70, 0.60), - new Point(1.00, 0.38), - new Point(0.62, 0.38) - ] -}; - -BouncingCanvasParticlesStage = Utilities.createSubclass(BouncingParticlesStage, - function() - { - BouncingParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); - this.context = this.element.getContext("2d"); - }, - - animate: function(timeDelta) - { - this.context.clearRect(0, 0, this.size.x, this.size.y); - this.particles.forEach(function(particle) { - particle.animate(timeDelta); - }); - } -}); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js b/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js deleted file mode 100644 index f3d0d81..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingCanvasShape = Utilities.createSubclass(BouncingCanvasParticle, - function(stage) - { - BouncingCanvasParticle.call(this, stage, stage.shape); - this._fill = stage.fill; - this._color0 = Stage.randomColor(); - this._color1 = Stage.randomColor(); - }, { - - _applyFill: function() - { - switch (this._fill) { - case "gradient": - var gradient = this.context.createLinearGradient(0, 0, this.size.width, 0); - gradient.addColorStop(0, this._color0); - gradient.addColorStop(1, this._color1); - this.context.fillStyle = gradient; - break; - - case "solid": - default: - this.context.fillStyle = this._color0; - break; - } - }, - - _drawShape: function() - { - this.context.beginPath(); - - switch (this._shape) { - case "rect": - this.context.rect(0, 0, this.size.width, this.size.height); - break; - - case "circle": - default: - var center = this.size.center; - var radius = Math.min(this.size.x, this.size.y) / 2; - this.context.arc(center.x, center.y, radius, 0, Math.PI * 2, true); - break; - } - - this.context.fill(); - }, - - _draw: function() - { - this.context.save(); - this._applyFill(); - this.applyRotation(); - this.applyClipping(); - this._drawShape(); - this.context.restore(); - } -}); - -BouncingCanvasShapesStage = Utilities.createSubclass(BouncingCanvasParticlesStage, - function () - { - BouncingCanvasParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options); - this.parseShapeParameters(options); - }, - - createParticle: function() - { - return new BouncingCanvasShape(this); - } -}); - -BouncingCanvasShapesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingCanvasShapesStage(), options); - } -); - -window.benchmarkClass = BouncingCanvasShapesBenchmark; - -})(); \ No newline at end of file diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js b/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js deleted file mode 100644 index 2f3fa53..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingCssImage = Utilities.createSubclass(BouncingParticle, - function(stage) - { - BouncingParticle.call(this, stage); - - this.element = document.createElement("img"); - this.element.style.width = this.size.x + "px"; - this.element.style.height = this.size.y + "px"; - this.element.setAttribute("src", stage.imageSrc); - - stage.element.appendChild(this.element); - this._move(); - }, { - - _move: function() - { - this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ(); - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this._move(); - } -}); - -BouncingCssImagesStage = Utilities.createSubclass(BouncingParticlesStage, - function() - { - BouncingParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); - this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg"; - }, - - createParticle: function() - { - return new BouncingCssImage(this); - }, - - particleWillBeRemoved: function(particle) - { - particle.element.remove(); - } -}); - -BouncingCssImagesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingCssImagesStage(), options); - } -); - -window.benchmarkClass = BouncingCssImagesBenchmark; - -})(); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js b/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js deleted file mode 100644 index d3048d4..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingCssShape = Utilities.createSubclass(BouncingParticle, - function(stage) - { - BouncingParticle.call(this, stage); - - this.element = this._createSpan(stage); - - switch (stage.fill) { - case "solid": - default: - this.element.style.backgroundColor = Stage.randomColor(); - break; - - case "gradient": - this.element.style.background = "linear-gradient(" + Stage.randomColor() + ", " + Stage.randomColor() + ")"; - break; - } - - if (stage.blend) - this.element.style.mixBlendMode = Stage.randomStyleMixBlendMode(); - - // Some browsers have not un-prefixed the css filter yet. - if (stage.filter) - Utilities.setElementPrefixedProperty(this.element, "filter", Stage.randomStyleFilter()); - - this._move(); - }, { - - _createSpan: function(stage) - { - var span = document.createElement("span"); - span.className = stage.shape + " " + stage.clip; - span.style.width = this.size.x + "px"; - span.style.height = this.size.y + "px"; - stage.element.appendChild(span); - return span; - }, - - _move: function() - { - this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px)" + this.rotater.rotateZ(); - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this.rotater.next(timeDelta); - this._move(); - } -}); - -BouncingCssShapesStage = Utilities.createSubclass(BouncingParticlesStage, - function() - { - BouncingParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); - this.parseShapeParameters(options); - }, - - createParticle: function() - { - return new BouncingCssShape(this); - }, - - particleWillBeRemoved: function(particle) - { - particle.element.remove(); - } -}); - -BouncingCssShapesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingCssShapesStage(), options); - } -); - -window.benchmarkClass = BouncingCssShapesBenchmark; - -})(); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js b/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js deleted file mode 100644 index 393d4b2..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -function BouncingParticle(stage) -{ - this._stageSize = stage.size; - this.size = stage.particleSize; - - this.position = Stage.randomPosition(stage.size.subtract(stage.particleSize)); - this._angle = Stage.randomAngle(); - this._velocity = Stage.randomVelocity(stage.maxVelocity); - this.rotater = Stage.randomRotater(); -} - -BouncingParticle.prototype = -{ - get center() - { - return this.position.add(this.size.center); - }, - - animate: function(timeDelta) - { - this.position = this.position.move(this._angle, this._velocity, timeDelta); - this.rotater.next(timeDelta); - - // If particle is going to move off right side - if (this.position.x + this.size.x > this._stageSize.x) { - // If direction is East-South, go West-South. - if (this._angle >= 0 && this._angle < Math.PI / 2) - this._angle = Math.PI - this._angle; - // If angle is East-North, go West-North. - else if (this._angle > Math.PI / 2 * 3) - this._angle = this._angle - (this._angle - Math.PI / 2 * 3) * 2; - // Make sure the particle does not go outside the stage boundaries. - this.position.x = this._stageSize.x - this.size.x; - } - - // If particle is going to move off left side - if (this.position.x < 0) { - // If angle is West-South, go East-South. - if (this._angle > Math.PI / 2 && this._angle < Math.PI) - this._angle = Math.PI - this._angle; - // If angle is West-North, go East-North. - else if (this._angle > Math.PI && this._angle < Math.PI / 2 * 3) - this._angle = this._angle + (Math.PI / 2 * 3 - this._angle) * 2; - // Make sure the particle does not go outside the stage boundaries. - this.position.x = 0; - } - - // If particle is going to move off bottom side - if (this.position.y + this.size.y > this._stageSize.y) { - // If direction is South, go North. - if (this._angle > 0 && this._angle < Math.PI) - this._angle = Math.PI * 2 - this._angle; - // Make sure the particle does not go outside the stage boundaries. - this.position.y = this._stageSize.y - this.size.y; - } - - // If particle is going to move off top side - if (this.position.y < 0) { - // If direction is North, go South. - if (this._angle > Math.PI && this._angle < Math.PI * 2) - this._angle = this._angle - (this._angle - Math.PI) * 2; - // Make sure the particle does not go outside the stage boundaries. - this.position.y = 0; - } - } -} - -BouncingParticlesStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - this.particles = []; - }, { - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - this.particleSize = new Point(parseInt(options["particleWidth"]) || 10, parseInt(options["particleHeight"]) || 10); - this.maxVelocity = Math.max(parseInt(options["maxVelocity"]) || 500, 100); - }, - - parseShapeParameters: function(options) - { - this.shape = options["shape"] || "circle"; - this.fill = options["fill"] || "solid"; - this.clip = options["clip"] || ""; - this.blend = options["blend"] || false; - this.filter = options["filter"] || false; - }, - - animate: function(timeDelta) - { - this.particles.forEach(function(particle) { - particle.animate(timeDelta); - }); - }, - - tune: function(count) - { - if (count == 0) - return; - - if (count > 0) { - for (var i = 0; i < count; ++i) - this.particles.push(this.createParticle()); - return; - } - - count = Math.min(-count, this.particles.length); - - if (typeof(this.particleWillBeRemoved) == "function") { - for (var i = 0; i < count; ++i) - this.particleWillBeRemoved(this.particles[this.particles.length - 1 - i]); - } - - this.particles.splice(-count, count); - }, - - complexity: function() - { - return this.particles.length; - } -}); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js b/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js deleted file mode 100644 index ae10dfd..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -BouncingSvgParticle = Utilities.createSubclass(BouncingParticle, - function(stage, shape) - { - BouncingParticle.call(this, stage); - this._shape = shape; - }, { - - _applyClipping: function(stage) - { - if (stage.clip != "star") - return; - - stage.ensureClipStarIsCreated(); - this.element.setAttribute("clip-path", "url(#star-clip)"); - }, - - _move: function() - { - var transform = "translate(" + this.position.x + ", " + this.position.y + ")"; - if (this._shape != "circle") - transform += this.rotater.rotate(this.size.center); - this.element.setAttribute("transform", transform); - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this._move(); - } -}); - -BouncingSvgParticlesStage = Utilities.createSubclass(BouncingParticlesStage, - function() - { - BouncingParticlesStage.call(this); - }, { - - _createDefs: function() - { - return Utilities.createSVGElement("defs", {}, {}, this.element); - }, - - _ensureDefsIsCreated: function() - { - return this.element.querySelector("defs") || this._createDefs(); - }, - - _createClipStar: function() - { - var attrs = { id: "star-clip", clipPathUnits: "objectBoundingBox" }; - var clipPath = Utilities.createSVGElement("clipPath", attrs, {}, this._ensureDefsIsCreated()); - - attrs = { d: "M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" }; - Utilities.createSVGElement("path", attrs, {}, clipPath); - return clipPath; - }, - - ensureClipStarIsCreated: function() - { - return this.element.querySelector("#star-clip") || this._createClipStar(); - }, - - particleWillBeRemoved: function(particle) - { - particle.element.remove(); - } -}); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js b/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js deleted file mode 100644 index 91be977..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingSvgShape = Utilities.createSubclass(BouncingSvgParticle, - function(stage) - { - BouncingSvgParticle.call(this, stage, stage.shape); - this._fill = stage.fill; - - this._createShape(stage); - this._applyClipping(stage); - this._applyFill(stage); - - this._move(); - }, { - - _createShape: function(stage) - { - switch (this._shape) { - case "rect": - var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y }; - this.element = Utilities.createSVGElement("rect", attrs, {}, stage.element); - break; - - case "circle": - default: - var attrs = { cx: this.size.x / 2, cy: this.size.y / 2, r: Math.min(this.size.x, this.size.y) / 2 }; - this.element = Utilities.createSVGElement("circle", attrs, {}, stage.element); - break; - } - }, - - _applyFill: function(stage) - { - switch (this._fill) { - case "gradient": - var gradient = stage.createGradient(2); - this.element.setAttribute("fill", "url(#" + gradient.getAttribute("id") + ")"); - break; - - case "solid": - default: - this.element.setAttribute("fill", Stage.randomColor()); - break; - } - } -}); - -BouncingSvgShapesStage = Utilities.createSubclass(BouncingSvgParticlesStage, - function() - { - BouncingSvgParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark, options); - this.parseShapeParameters(options); - this._gradientsCount = 0; - }, - - createGradient: function(stops) - { - var attrs = { id: "gradient-" + ++this._gradientsCount }; - var gradient = Utilities.createSVGElement("linearGradient", attrs, {}, this._ensureDefsIsCreated()); - - for (var i = 0; i < stops; ++i) { - attrs = { offset: i * 100 / (stops - 1) + "%", 'stop-color': Stage.randomColor() }; - Utilities.createSVGElement("stop", attrs, {}, gradient); - } - - return gradient; - }, - - createParticle: function() - { - return new BouncingSvgShape(this); - }, - - particleWillBeRemoved: function(particle) - { - BouncingSvgParticlesStage.prototype.particleWillBeRemoved.call(this, particle); - - var fill = particle.element.getAttribute("fill"); - if (fill.indexOf("url(#") != 0) - return; - - var gradient = this.element.querySelector(fill.substring(4, fill.length - 1)); - this._ensureDefsIsCreated().removeChild(gradient); - } -}); - -BouncingSvgShapesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingSvgShapesStage(), options); - } -); - -window.benchmarkClass = BouncingSvgShapesBenchmark; - -})(); diff --git a/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js b/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js deleted file mode 100644 index d8be60f..0000000 --- a/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingTaggedImage = Utilities.createSubclass(BouncingParticle, - function(stage) - { - BouncingParticle.call(this, stage); - - this.element = document.createElement("img"); - this.element.style.width = this.size.x + "px"; - this.element.style.height = this.size.y + "px"; - this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src); - - stage.element.appendChild(this.element); - this._move(); - }, { - - _move: function() - { - this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ(); - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this._move(); - } -}); - -BouncingTaggedImagesStage = Utilities.createSubclass(BouncingParticlesStage, - - function() - { - BouncingParticlesStage.call(this); - }, { - - imageSrcs: [ - "image1", - "image2", - "image3", - "image4", - "image5", - ], - images: [], - - initialize: function(benchmark, options) - { - BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); - - var lastPromise; - var images = this.images; - this.imageSrcs.forEach(function(imageSrc) { - var promise = this._loadImage("resources/" + imageSrc + ".jpg"); - if (!lastPromise) - lastPromise = promise; - else { - lastPromise = lastPromise.then(function(img) { - images.push(img); - return promise; - }); - } - }, this); - - lastPromise.then(function(img) { - images.push(img); - benchmark.readyPromise.resolve(); - }); - }, - - _loadImage: function(src) { - var img = new Image; - var promise = new SimplePromise; - - img.onload = function(e) { - promise.resolve(e.target); - }; - - img.src = src; - return promise; - }, - - createParticle: function() - { - return new BouncingTaggedImage(this); - }, - - particleWillBeRemoved: function(particle) - { - particle.element.remove(); - } -}); - -BouncingTaggedImagesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new BouncingTaggedImagesStage(), options); - }, { - - waitUntilReady: function() { - this.readyPromise = new SimplePromise; - return this.readyPromise; - } -}); - -window.benchmarkClass = BouncingTaggedImagesBenchmark; - -})(); diff --git a/MotionMark/tests/bouncing-particles/resources/image1.jpg b/MotionMark/tests/bouncing-particles/resources/image1.jpg deleted file mode 100644 index ea7a4c1..0000000 Binary files a/MotionMark/tests/bouncing-particles/resources/image1.jpg and /dev/null differ diff --git a/MotionMark/tests/bouncing-particles/resources/image2.jpg b/MotionMark/tests/bouncing-particles/resources/image2.jpg deleted file mode 100644 index 697272d..0000000 Binary files a/MotionMark/tests/bouncing-particles/resources/image2.jpg and /dev/null differ diff --git a/MotionMark/tests/bouncing-particles/resources/image3.jpg b/MotionMark/tests/bouncing-particles/resources/image3.jpg deleted file mode 100644 index 6e5964e..0000000 Binary files a/MotionMark/tests/bouncing-particles/resources/image3.jpg and /dev/null differ diff --git a/MotionMark/tests/bouncing-particles/resources/image4.jpg b/MotionMark/tests/bouncing-particles/resources/image4.jpg deleted file mode 100644 index 806f548..0000000 Binary files a/MotionMark/tests/bouncing-particles/resources/image4.jpg and /dev/null differ diff --git a/MotionMark/tests/bouncing-particles/resources/image5.jpg b/MotionMark/tests/bouncing-particles/resources/image5.jpg deleted file mode 100644 index d7971f6..0000000 Binary files a/MotionMark/tests/bouncing-particles/resources/image5.jpg and /dev/null differ diff --git a/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html b/MotionMark/tests/core/canvas-arcs.html similarity index 52% rename from MotionMark/tests/bouncing-particles/bouncing-canvas-images.html rename to MotionMark/tests/core/canvas-arcs.html index 90264c9..3fec754 100644 --- a/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html +++ b/MotionMark/tests/core/canvas-arcs.html @@ -1,5 +1,5 @@ - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/core/design.html b/MotionMark/tests/core/design.html index 0f30dfd..e4bc55f 100644 --- a/MotionMark/tests/core/design.html +++ b/MotionMark/tests/core/design.html @@ -1,5 +1,5 @@ - - - - - - - - -
- - - - - - - - diff --git a/MotionMark/tests/core/resources/compass100.png b/MotionMark/tests/core/images/compass100.png similarity index 100% rename from MotionMark/tests/core/resources/compass100.png rename to MotionMark/tests/core/images/compass100.png diff --git a/MotionMark/tests/core/resources/console100.png b/MotionMark/tests/core/images/console100.png similarity index 100% rename from MotionMark/tests/core/resources/console100.png rename to MotionMark/tests/core/images/console100.png diff --git a/MotionMark/tests/core/resources/contribute100.png b/MotionMark/tests/core/images/contribute100.png similarity index 100% rename from MotionMark/tests/core/resources/contribute100.png rename to MotionMark/tests/core/images/contribute100.png diff --git a/MotionMark/tests/core/resources/debugger100.png b/MotionMark/tests/core/images/debugger100.png similarity index 100% rename from MotionMark/tests/core/resources/debugger100.png rename to MotionMark/tests/core/images/debugger100.png diff --git a/MotionMark/tests/core/resources/inspector100.png b/MotionMark/tests/core/images/inspector100.png similarity index 100% rename from MotionMark/tests/core/resources/inspector100.png rename to MotionMark/tests/core/images/inspector100.png diff --git a/MotionMark/tests/core/resources/layout100.png b/MotionMark/tests/core/images/layout100.png similarity index 100% rename from MotionMark/tests/core/resources/layout100.png rename to MotionMark/tests/core/images/layout100.png diff --git a/MotionMark/tests/core/resources/performance100.png b/MotionMark/tests/core/images/performance100.png similarity index 100% rename from MotionMark/tests/core/resources/performance100.png rename to MotionMark/tests/core/images/performance100.png diff --git a/MotionMark/tests/core/resources/script100.png b/MotionMark/tests/core/images/script100.png similarity index 100% rename from MotionMark/tests/core/resources/script100.png rename to MotionMark/tests/core/images/script100.png diff --git a/MotionMark/tests/core/resources/shortcuts100.png b/MotionMark/tests/core/images/shortcuts100.png similarity index 100% rename from MotionMark/tests/core/resources/shortcuts100.png rename to MotionMark/tests/core/images/shortcuts100.png diff --git a/MotionMark/tests/core/resources/standards100.png b/MotionMark/tests/core/images/standards100.png similarity index 100% rename from MotionMark/tests/core/resources/standards100.png rename to MotionMark/tests/core/images/standards100.png diff --git a/MotionMark/tests/core/resources/storage100.png b/MotionMark/tests/core/images/storage100.png similarity index 100% rename from MotionMark/tests/core/resources/storage100.png rename to MotionMark/tests/core/images/storage100.png diff --git a/MotionMark/tests/core/resources/styles100.png b/MotionMark/tests/core/images/styles100.png similarity index 100% rename from MotionMark/tests/core/resources/styles100.png rename to MotionMark/tests/core/images/styles100.png diff --git a/MotionMark/tests/core/resources/timeline100.png b/MotionMark/tests/core/images/timeline100.png similarity index 100% rename from MotionMark/tests/core/resources/timeline100.png rename to MotionMark/tests/core/images/timeline100.png diff --git a/MotionMark/tests/core/leaves.html b/MotionMark/tests/core/leaves.html index 7d9bd3f..31d515c 100644 --- a/MotionMark/tests/core/leaves.html +++ b/MotionMark/tests/core/leaves.html @@ -1,5 +1,5 @@ - - - - - diff --git a/MotionMark/tests/core/resources/console.svg b/MotionMark/tests/core/resources/console.svg deleted file mode 100644 index e3c7611..0000000 --- a/MotionMark/tests/core/resources/console.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/contribute.svg b/MotionMark/tests/core/resources/contribute.svg deleted file mode 100644 index 68860ef..0000000 --- a/MotionMark/tests/core/resources/contribute.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/debugger.svg b/MotionMark/tests/core/resources/debugger.svg deleted file mode 100644 index 646ddf4..0000000 --- a/MotionMark/tests/core/resources/debugger.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MotionMark/tests/core/resources/design.js b/MotionMark/tests/core/resources/design.js index ff09468..7e3ed31 100644 --- a/MotionMark/tests/core/resources/design.js +++ b/MotionMark/tests/core/resources/design.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,122 +22,107 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -(function() { - -var TextStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - - this.testElements = []; - this._offsetIndex = 0; - }, { - - shadowFalloff: new UnitBezier(new Point(0.015, 0.750), new Point(0.755, 0.235)), - shimmerAverage: 0, - shimmerMax: 0.5, - millisecondsPerRotation: 1000 / (.26 * Math.PI * 2), - particleDistanceX: 1.5, - particleDistanceY: .5, - lightnessMin: 13, - lightnessMax: 94, - gradients: [ - [10, 176, 176, 209, 148, 140], - [171, 120, 154, 245, 196, 154], - [224, 99, 99, 71, 134, 148], - [101, 100, 117, 80, 230, 175], - [232, 165, 30, 69, 186, 172] - ], - - initialize: function(benchmark) - { - Stage.prototype.initialize.call(this, benchmark); - - this._template = document.getElementById("template"); - - const templateSize = Point.elementClientSize(this._template); - this._offset = this.size.subtract(templateSize).multiply(.5); - this._maxOffset = templateSize.height / 4; - - this._template.style.left = this._offset.width + "px"; - this._template.style.top = this._offset.height + "px"; - - this._stepProgress = 0; - }, - - tune: function(count) - { - if (count == 0) - return; - if (count < 0) { - this._offsetIndex = Math.max(this._offsetIndex + count, 0); - for (let i = this._offsetIndex; i < this.testElements.length; ++i) - this.testElements[i].style.visibility = "hidden"; +class TextTable { + static shimmerAverage = 0; + static shimmerMax = 0.5; + static shadowFalloff = new UnitBezier(new Point(0.015, 0.750), new Point(0.755, 0.235)); + table; - this._stepProgress = 1 / this._offsetIndex; - return; - } + constructor(table) { + this.table = table; + } - this._offsetIndex = this._offsetIndex + count; - this._stepProgress = 1 / this._offsetIndex; + show() { + this.table.style.visibility = "visible"; + } - const index = Math.min(this._offsetIndex, this.testElements.length); - for (let i = 0; i < index; ++i) - this.testElements[i].style.visibility = "visible"; + hide() { + this.table.style.visibility = "hidden"; + } - if (this._offsetIndex <= this.testElements.length) - return; + move(progress, maxPosition) { + let x = Math.lerp(progress, 0, maxPosition.x); + let y = Math.lerp(progress, 0, maxPosition.y); + this.table.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)"; + } - for (let i = this.testElements.length; i < this._offsetIndex; ++i) { - const clone = this._template.cloneNode(true); - this.testElements.push(clone); - this.element.insertBefore(clone, this.element.firstChild); - } - }, + setColor(progress, offset, gradient) { + let colorProgress = TextTable.shadowFalloff.solve(progress); + const shimmer = Math.sin(offset - colorProgress); + colorProgress = Math.max(Math.min(colorProgress + Math.lerp(shimmer, TextTable.shimmerAverage, TextTable.shimmerMax), 1), 0); - animate: function(timeDelta) - { - const angle = Stage.dateCounterValue(this.millisecondsPerRotation); + let r = Math.round(Math.lerp(colorProgress, gradient[0], gradient[3])); + let g = Math.round(Math.lerp(colorProgress, gradient[1], gradient[4])); + let b = Math.round(Math.lerp(colorProgress, gradient[2], gradient[5])); + this.table.style.color = "rgb(" + r + "," + g + "," + b + ")"; + } - const gradient = this.gradients[Math.floor(angle / (Math.PI * 2)) % this.gradients.length]; - const offset = Stage.dateCounterValue(200); - const maxX = Math.sin(angle) * this._maxOffset; - const maxY = Math.cos(angle) * this._maxOffset; + animate(progress, maxPosition, offset, gradient) { + this.move(progress, maxPosition); + this.setColor(progress, offset, gradient); + } +} - let progress = 0; - for (let i = 0; i < this._offsetIndex; ++i) { - const element = this.testElements[i]; - - let colorProgress = this.shadowFalloff.solve(progress); - const shimmer = Math.sin(offset - colorProgress); - colorProgress = Math.max(Math.min(colorProgress + Utilities.lerp(shimmer, this.shimmerAverage, this.shimmerMax), 1), 0); - const r = Math.round(Utilities.lerp(colorProgress, gradient[0], gradient[3])); - const g = Math.round(Utilities.lerp(colorProgress, gradient[1], gradient[4])); - const b = Math.round(Utilities.lerp(colorProgress, gradient[2], gradient[5])); - element.style.color = "rgb(" + r + "," + g + "," + b + ")"; - - const x = Utilities.lerp(i / this._offsetIndex, 0, maxX); - const y = Utilities.lerp(i / this._offsetIndex, 0, maxY); - element.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)"; - - progress += this._stepProgress; - } - }, +class TextTablesStage extends ReusableParticlesStage { + gradients = [ + [ 10, 176, 176, 209, 148, 140], + [171, 120, 154, 245, 196, 154], + [224, 99, 99, 71, 134, 148], + [101, 100, 117, 80, 230, 175], + [232, 165, 30, 69, 186, 172] + ]; + millisecondsPerRotation = 1000 / (.26 * Math.PI * 2); + template; + templateSize; + offset; + shadowFalloff; + + constructor() { + super(); + + this.template = document.getElementById("template"); + this.templateSize = Size.elementClientSize(this.template); + + this.offset = new Size(this.size); + this.offset.subtract(this.templateSize); + this.offset.divideBy(2); + + this.template.style.left = this.offset.width + "px"; + this.template.style.top = this.offset.height + "px"; + } - complexity: function() - { - return 1 + this._offsetIndex; + createParticle() { + let table = this.template.cloneNode(true); + this.element.insertBefore(table, this.element.firstChild); + return new TextTable(table); } -}); -var TextBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new TextStage(), options); + animate(timestamp, lastFrameLength) { + let activeParticles = this.activeParticles(); + if (activeParticles.length == 0) + return; + + let angle = Random.dateCounterValue(this.millisecondsPerRotation); + let gradient = this.gradients[Math.floor(angle / (Math.PI * 2)) % this.gradients.length]; + let offset = Random.dateCounterValue(200); + let magnitude = Math.min(this.templateSize.height / 4, activeParticles.length * 2); + let maxPosition = Point.fromVector(magnitude, angle); + + let step = 1 / activeParticles.length; + let progress = 0; + + for (let particle of activeParticles) { + particle.animate(progress, maxPosition, offset, gradient); + progress += step; + } } -); +} -window.benchmarkClass = TextBenchmark; +class TextTableAnimator extends Animator { + constructor(test, settings) { + super(new TextTablesStage(), test, settings); + } +} -}()); +window.animatorClass = TextTableAnimator; diff --git a/MotionMark/tests/core/resources/focus.js b/MotionMark/tests/core/resources/focus.js deleted file mode 100644 index ae51e5d..0000000 --- a/MotionMark/tests/core/resources/focus.js +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -var minimumDiameter = 30; -var sizeVariance = 20; -var travelDistance = 50; - -var minBlurValue = 1; -var maxBlurValue = 10; - -var opacityMultiplier = 30; -var focusDuration = 1000; -var movementDuration = 2500; - -var FocusElement = Utilities.createClass( - function(stage) - { - var size = minimumDiameter + sizeVariance; - - // Size and blurring are a function of depth. - this._depth = Pseudo.random(); - var distance = Utilities.lerp(this._depth, 0, sizeVariance); - size -= distance; - - var top = Stage.random(0, stage.size.height - size); - var left = Stage.random(0, stage.size.width - size); - - this.particle = document.createElement("div"); - this.particle.style.width = size + "px"; - this.particle.style.height = size + "px"; - this.particle.style.top = top + "px"; - this.particle.style.left = left + "px"; - this.particle.style.zIndex = Math.round((1 - this._depth) * 10); - - var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1); - this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; - this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; - - this.animate(stage, 0, 0); - }, { - - hide: function() - { - this.particle.style.display = "none"; - }, - - show: function() - { - this.particle.style.display = "block"; - }, - - animate: function(stage, sinFactor, cosFactor) - { - var top = sinFactor * this._sinMultiplier; - var left = cosFactor * this._cosMultiplier; - var distance = Math.abs(this._depth - stage.focalPoint); - var blur = Utilities.lerp(distance, minBlurValue, maxBlurValue); - var opacity = Math.max(5, opacityMultiplier * (1 - distance)); - - Utilities.setElementPrefixedProperty(this.particle, "filter", "blur(" + blur + "px) opacity(" + opacity + "%)"); - this.particle.style.transform = "translate3d(" + left + "%, " + top + "%, 0)"; - } -}); - -var FocusStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - }, { - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - - this._testElements = []; - this._offsetIndex = 0; - this.focalPoint = 0.5; - }, - - complexity: function() - { - return this._offsetIndex; - }, - - tune: function(count) - { - if (count == 0) - return; - - if (count < 0) { - this._offsetIndex = Math.max(0, this._offsetIndex + count); - for (var i = this._offsetIndex; i < this._testElements.length; ++i) - this._testElements[i].hide(); - return; - } - - var newIndex = this._offsetIndex + count; - for (var i = this._testElements.length; i < newIndex; ++i) { - var obj = new FocusElement(this); - this._testElements.push(obj); - this.element.appendChild(obj.particle); - } - for (var i = this._offsetIndex; i < newIndex; ++i) - this._testElements[i].show(); - this._offsetIndex = newIndex; - }, - - animate: function() - { - var time = this._benchmark.timestamp; - var sinFactor = Math.sin(time / movementDuration); - var cosFactor = Math.cos(time / movementDuration); - - this.focalPoint = 0.5 + 0.5 * Math.sin(time / focusDuration); - - for (var i = 0; i < this._offsetIndex; ++i) - this._testElements[i].animate(this, sinFactor, cosFactor); - } -}); - -var FocusBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new FocusStage(), options); - } -); - -window.benchmarkClass = FocusBenchmark; - -}()); diff --git a/MotionMark/tests/core/resources/image-canvases.js b/MotionMark/tests/core/resources/image-canvases.js new file mode 100644 index 0000000..0f4fe73 --- /dev/null +++ b/MotionMark/tests/core/resources/image-canvases.js @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +class ImageCanvas { + static size = new Size(50, 50); + static pixelStride = 4; + static rowStride = ImageCanvas.size.width * ImageCanvas.pixelStride; + static weightNegativeThreshold = 0.04; + static weightPositiveThreshold = 0.96; + stage; + image; + canvas; + + constructor(stage) { + this.stage = stage; + this.image = Random.itemInArray(stage.images); + + this.canvas = document.createElement('canvas'); + this.canvas.width = ImageCanvas.size.width; + this.canvas.height = ImageCanvas.size.height; + this.canvas.style.width = ImageCanvas.size.width + 'px'; + this.canvas.style.height = ImageCanvas.size.height + 'px'; + this.stage.element.appendChild(this.canvas); + + this.reset(); + } + + show() { + this.canvas.style.display = "block"; + this.reset(); + } + + hide() { + this.canvas.style.display = "none"; + } + + reset() { + let tiles = this.stage.size.dividedBy(ImageCanvas.size); + let left = Random.integer(0, Math.floor(tiles.width) - 1) * ImageCanvas.size.width; + let top = Random.integer(0, Math.floor(tiles.height) - 1) * ImageCanvas.size.height; + + this.canvas.style.top = top + 'px'; + this.canvas.style.left = left + 'px'; + } + + randomDistance() + { + let factor = ImageCanvas.weightPositiveThreshold - ImageCanvas.weightNegativeThreshold; + let xOffset = Math.floor((Pseudo.random() - ImageCanvas.weightNegativeThreshold) / factor); + let yOffset = Math.floor((Pseudo.random() - ImageCanvas.weightNegativeThreshold) / factor); + return yOffset * ImageCanvas.rowStride + xOffset * ImageCanvas.pixelStride; + } + + animate(timestamp, lastFrameLength) { + let context = this.canvas.getContext("2d"); + + let imageData = context.getImageData(0, 0, ImageCanvas.size.width, ImageCanvas.size.height); + let dataLength = imageData.data.length; + let didDraw = false; + + for (let j = 0; j < dataLength; j += ImageCanvas.pixelStride) { + if (imageData.data[j + 3] === 0) + continue; + + // Get random neighboring pixel color. + let neighbor = (j + this.randomDistance()) % dataLength; + + // Update the RGB data + imageData.data[j] = imageData.data[neighbor]; + imageData.data[j + 1] = imageData.data[neighbor + 1]; + imageData.data[j + 2] = imageData.data[neighbor + 2]; + imageData.data[j + 3] = imageData.data[neighbor + 3]; + didDraw = true; + } + + if (didDraw) + context.putImageData(imageData, 0, 0); + else { + this.reset(); + context.drawImage(this.image, 0, 0, ImageCanvas.size.width, ImageCanvas.size.height); + } + } +} + +class ImageCanvasesStage extends ReusableParticlesStage { + imageSources; + images; + + constructor() { + super(); + + this.imageSources = [ + "compass", + "console", + "contribute", + "debugger", + "inspector", + "layout", + "performance", + "script", + "shortcuts", + "standards", + "storage", + "styles", + "timeline" + ]; + this.images = []; + } + + loadImages() { + return this.imageSources.map((imageSource) => { + return new Promise((resolve) => { + let image = new Image; + image.onload = (e) => { + resolve({ width: image.width, height: image.height }); + }; + image.src = "../core/images/" + imageSource + "100.png"; + this.images.push(image); + }); + }); + } + + createParticle() { + return new ImageCanvas(this); + } +} + +class ImageCanvasesAnimator extends Animator { + constructor(test, settings) { + super(new ImageCanvasesStage(), test, settings); + } + + async run() { + await Promise.all(this.stage.loadImages()); + return super.run(); + } +} + +window.animatorClass = ImageCanvasesAnimator; diff --git a/MotionMark/tests/core/resources/image-data.js b/MotionMark/tests/core/resources/image-data.js deleted file mode 100644 index 1940c3a..0000000 --- a/MotionMark/tests/core/resources/image-data.js +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -var ImageDataStage = Utilities.createSubclass(Stage, - function() { - Stage.call(this); - - this.testElements = []; - this._offsetIndex = 0; - }, { - - imageWidth: 50, - imageHeight: 50, - pixelStride: 4, - rowStride: 200, - weightNegativeThreshold: 0.04, - weightPositiveThreshold: 0.96, - imageSrcs: [ - "compass", - "console", - "contribute", - "debugger", - "inspector", - "layout", - "performance", - "script", - "shortcuts", - "standards", - "storage", - "styles", - "timeline" - ], - images: [], - - initialize: function(benchmark) - { - Stage.prototype.initialize.call(this, benchmark); - - var lastPromise; - var images = this.images; - this.imageSrcs.forEach(function(imageSrc) { - var promise = this._loadImage("resources/" + imageSrc + ".svg"); - if (!lastPromise) - lastPromise = promise; - else { - lastPromise = lastPromise.then(function(img) { - images.push(img); - return promise; - }); - } - }, this); - - lastPromise.then(function(img) { - images.push(img); - benchmark.readyPromise.resolve(); - }.bind(this)); - }, - - _loadImage: function(src) { - var img = new Image; - var promise = new SimplePromise; - - img.addEventListener('load', function onImageLoad(e) { - img.removeEventListener('load', onImageLoad); - promise.resolve(img); - }); - - img.src = src; - return promise; - }, - - tune: function(count) - { - if (count == 0) - return; - - if (count < 0) { - this._offsetIndex = Math.max(this._offsetIndex + count, 0); - for (var i = this._offsetIndex; i < this.testElements.length; ++i) - this.testElements[i].style.display = "none"; - return; - } - - this._offsetIndex = this._offsetIndex + count; - var index = Math.min(this._offsetIndex, this.testElements.length); - for (var i = 0; i < index; ++i) { - this.testElements[i].style.display = "block"; - this._refreshElement(this.testElements[i]); - } - if (this._offsetIndex <= this.testElements.length) - return; - - index = this._offsetIndex - this.testElements.length; - for (var i = 0; i < index; ++i) { - var element = this._createTestElement(); - this.testElements.push(element); - this.element.appendChild(element); - } - }, - - _createTestElement: function() { - var element = document.createElement('canvas'); - element.width = this.imageWidth; - element.height = this.imageHeight; - element.style.width = this.imageWidth + 'px'; - element.style.height = this.imageHeight + 'px'; - - this._refreshElement(element); - return element; - }, - - _refreshElement: function(element) { - var top = Stage.randomInt(0, Math.floor((this.size.height - this.imageHeight) / this.imageHeight)) * this.imageHeight; - var left = Stage.randomInt(0, Math.floor((this.size.width - this.imageWidth) / this.imageWidth)) * this.imageWidth; - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - }, - - animate: function(timeDelta) { - for (var i = 0; i < this._offsetIndex; ++i) { - var element = this.testElements[i]; - var context = element.getContext("2d"); - - // Get image data - var imageData = context.getImageData(0, 0, this.imageWidth, this.imageHeight); - - var didDraw = false, - neighborPixelIndex, - dataLen = imageData.data.length; - for (var j = 0; j < dataLen; j += this.pixelStride) { - if (imageData.data[j + 3] === 0) - continue; - - // get random neighboring pixel color - neighborPixelIndex = this._getRandomNeighboringPixelIndex(j, dataLen); - - // Update the RGB data - imageData.data[j] = imageData.data[neighborPixelIndex]; - imageData.data[j + 1] = imageData.data[neighborPixelIndex + 1]; - imageData.data[j + 2] = imageData.data[neighborPixelIndex + 2]; - imageData.data[j + 3] = imageData.data[neighborPixelIndex + 3]; - didDraw = true; - } - - if (didDraw) - context.putImageData(imageData, 0, 0); - else { - this._refreshElement(element); - element.getContext("2d").drawImage(Stage.randomElementInArray(this.images), 0, 0, this.imageWidth, this.imageHeight); - } - } - }, - - _getRandomNeighboringPixelIndex: function(pixelIdx, pixelArrayLength) - { - var xOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold)); - var yOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold)); - return (pixelIdx + this.pixelStride * xOffset + this.rowStride * yOffset) % pixelArrayLength; - }, - - complexity: function() - { - return this._offsetIndex; - } -}); - -var ImageDataBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new ImageDataStage(), options); - }, { - - waitUntilReady: function() { - this.readyPromise = new SimplePromise; - return this.readyPromise; - } -}); - -window.benchmarkClass = ImageDataBenchmark; - -}()); diff --git a/MotionMark/tests/core/resources/inspector.svg b/MotionMark/tests/core/resources/inspector.svg deleted file mode 100644 index 68cc413..0000000 --- a/MotionMark/tests/core/resources/inspector.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/layout.svg b/MotionMark/tests/core/resources/layout.svg deleted file mode 100644 index 73db97e..0000000 --- a/MotionMark/tests/core/resources/layout.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/leaves.js b/MotionMark/tests/core/resources/leaves.js index e23e383..7f03d83 100644 --- a/MotionMark/tests/core/resources/leaves.js +++ b/MotionMark/tests/core/resources/leaves.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 Apple Inc. All rights reserved. + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,73 +22,77 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -(function() { - -window.Leaf = Utilities.createSubclass(Particle, - function(stage) - { - this.element = document.createElement("img"); - this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src); - stage.element.appendChild(this.element); - - Particle.call(this, stage); - }, { - - sizeMinimum: 20, - sizeRange: 30, - usesOpacity: true, - - reset: function() - { - Particle.prototype.reset.call(this); - this.element.style.width = this.size.x + "px"; - this.element.style.height = this.size.y + "px"; - - if (this.usesOpacity) { - this._opacity = .01; - this._opacityRate = 0.02 * Stage.random(1, 6); - } else - this._life = Stage.randomInt(20, 100); - - this._position = new Point(Stage.random(0, this.maxPosition.x), Stage.random(-this.size.height, this.maxPosition.y)); - this._velocity = new Point(Stage.random(-6, -2), .1 * this.size.y + Stage.random(-1, 1)); - }, - - animate: function(timeDelta) - { - this.rotater.next(timeDelta); - - this._position.x += this._velocity.x + 8 * this.stage.focusX; - this._position.y += this._velocity.y; - - if (this.usesOpacity) { - this._opacity += this._opacityRate; - if (this._opacity > 1) { - this._opacity = 1; - this._opacityRate *= -1; - } else if (this._opacity < 0 || this._position.y > this.stage.size.height) - this.reset(); - } else { - this._life--; - if (!this._life || this._position.y > this.stage.size.height) - this.reset(); - } - if (this._position.x < -this.size.width || this._position.x > this.stage.size.width) - this._position.x = this._position.x - Math.sign(this._position.x) * (this.size.width + this.stage.size.width); - this.move(); - }, +class Leaf extends ResettableParticle { + static minSide = 20; + static maxSide = 50; + image; + position; + velocity; + opacity; + opacityRate; + + constructor(stage) { + super(stage, Leaf.minSide, Leaf.maxSide); + + // Create the element and set its source. + this.image = document.createHTMLElement('img', { + src: Random.itemInArray(stage.images).src + }, stage.element); + + // Move it to some initial position. + this.reset(); + this.resize(); + this.move(0); + } - move: function() - { - this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); - this.element.style.opacity = this._opacity; + remove() { + this.image.remove(); } -}); -Utilities.extendObject(ParticlesStage.prototype, { + reset() { + super.reset(); + + this.opacity = .01; + this.opacityRate = 0.02 * Random.number(1, 6); - imageSrcs: [ + this.position = new Point(Random.number(0, this.bouncingRect.maxX), Random.number(-this.size.height, this.bouncingRect.maxY)); + this.velocity = new Point(Random.number(-6, -2), .1 * this.size.height + Random.number(-1, 1)); + } + + move(timestamp) { + this.image.style.transform = "translate(" + this.position.x + "px, " + this.position.y + "px)" + this.rotator.rotateZ(timestamp); + this.image.style.opacity = this.opacity; + } + + resize() { + this.image.style.width = this.size.width + "px"; + this.image.style.height = this.size.height + "px"; + + } + + animate(timestamp, lastFrameLength) { + this.position.x += this.velocity.x + 8; // * this.stage.focusX; + this.position.y += this.velocity.y; + + this.opacity += this.opacityRate; + if (this.opacity > 1) { + this.opacity = 1; + this.opacityRate *= -1; + } else if (this.opacity < 0 || this.position.y > this.stage.size.height) { + this.reset(); + this.resize(); + } + + if (this.position.x < -this.size.width || this.position.x > this.stage.size.width) + this.position.x = this.position.x - Math.sign(this.position.x) * (this.size.width + this.stage.size.width); + + this.move(timestamp); + } +} + +class LeavesStage extends DisposableParticlesStage { + imageSources = [ "compass", "console", "contribute", @@ -102,78 +106,40 @@ Utilities.extendObject(ParticlesStage.prototype, { "storage", "styles", "timeline" - ], - images: [], - - initialize: function(benchmark) - { - Stage.prototype.initialize.call(this, benchmark); - - var lastPromise; - var images = this.images; - this.imageSrcs.forEach(function(imageSrc) { - var promise = this._loadImage("../core/resources/" + imageSrc + "100.png"); - if (!lastPromise) - lastPromise = promise; - else { - lastPromise = lastPromise.then(function(img) { - images.push(img); - return promise; - }); - } - }, this); - - lastPromise.then(function(img) { - images.push(img); - benchmark.readyPromise.resolve(); - }); - }, - - _loadImage: function(src) { - var img = new Image; - var promise = new SimplePromise; - - img.onload = function(e) { - promise.resolve(e.target); - }; - - img.src = src; - return promise; - }, - - animate: function(timeDelta) - { - this.focusX = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(10000) * Math.PI * 2); - timeDelta /= 4; - this.particles.forEach(function(particle) { - particle.animate(timeDelta); + ]; + images = []; + + loadImages() { + return this.imageSources.map((imageSource) => { + return new Promise((resolve) => { + let image = new Image; + image.onload = (e) => { + resolve({ width: image.width, height: image.height }); + }; + image.src = "../core/images/" + imageSource + "100.png"; + this.images.push(image); + }); }); - }, + } - createParticle: function() - { + createParticle() { return new Leaf(this); - }, - - willRemoveParticle: function(particle) - { - particle.element.remove(); } -}); - -var LeavesBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new ParticlesStage(), options); - }, { - waitUntilReady: function() { - this.readyPromise = new SimplePromise; - return this.readyPromise; + removeParticle(leaf) { + leaf.remove(); } +} -}); +class LeavesAnimator extends Animator { + constructor(test, settings) { + super(new LeavesStage(), test, settings); + } -window.benchmarkClass = LeavesBenchmark; + async run() { + await Promise.all(this.stage.loadImages()); + return super.run(); + } +} -})(); +window.animatorClass = LeavesAnimator; diff --git a/MotionMark/tests/core/resources/multiply.js b/MotionMark/tests/core/resources/multiply.js index c21febc..555d5e6 100644 --- a/MotionMark/tests/core/resources/multiply.js +++ b/MotionMark/tests/core/resources/multiply.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,132 +22,124 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -(function() { - -var MultiplyStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - this.tiles = []; - this._offsetIndex = 0; - }, { - - visibleCSS: [ - ["display", "none", "block"] - ], - totalRows: 68, - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - var tileSize = Math.round(this.size.height / this.totalRows); - if (options.visibleCSS) - this.visibleCSS = options.visibleCSS; - - // Fill the scene with elements - var x = Math.round((this.size.width - tileSize) / 2); - var y = Math.round((this.size.height - tileSize) / 2); - var tileStride = tileSize; - var direction = 0; - var spiralCounter = 2; - var nextIndex = 1; - var maxSide = Math.floor(y / tileStride) * 2 + 1; - this._centerSpiralCount = maxSide * maxSide; - for (var i = 0; i < this._centerSpiralCount; ++i) { - this._addTile(x, y, tileSize, Stage.randomInt(0, 359)); - - if (i == nextIndex) { - direction = (direction + 1) % 4; - spiralCounter++; - nextIndex += spiralCounter >> 1; - } - if (direction == 0) - x += tileStride; - else if (direction == 1) - y -= tileStride; - else if (direction == 2) - x -= tileStride; - else - y += tileStride; - } - - this._sidePanelCount = maxSide * Math.floor((this.size.width - x) / tileStride) * 2; - for (var i = 0; i < this._sidePanelCount; ++i) { - var sideX = x + Math.floor(Math.floor(i / maxSide) / 2) * tileStride; - var sideY = y - tileStride * (i % maxSide); - - if (Math.floor(i / maxSide) % 2 == 1) - sideX = this.size.width - sideX - tileSize + 1; - this._addTile(sideX, sideY, tileSize, Stage.randomInt(0, 359)); - } - }, - - _addTile: function(x, y, tileSize, rotateDeg) - { - var tile = Utilities.createElement("div", { class: "div-" + Stage.randomInt(0,6) }, this.element); - var halfTileSize = tileSize / 2; - tile.style.left = x + 'px'; - tile.style.top = y + 'px'; - tile.style.width = tileSize + 'px'; - tile.style.height = tileSize + 'px'; - var visibleCSS = this.visibleCSS[this.tiles.length % this.visibleCSS.length]; - tile.style[visibleCSS[0]] = visibleCSS[1]; - - var distance = 1 / tileSize * this.size.multiply(0.5).subtract(new Point(x + halfTileSize, y + halfTileSize)).length(); - this.tiles.push({ - element: tile, - rotate: rotateDeg, - step: Math.max(3, distance / 1.5), - distance: distance, - active: false, - visibleCSS: visibleCSS, - }); - }, - - complexity: function() - { - return this._offsetIndex; - }, - - tune: function(count) - { - this._offsetIndex = Math.max(0, Math.min(this._offsetIndex + count, this.tiles.length)); - this._distanceFactor = 1.5 * (1 - 0.5 * Math.max(this._offsetIndex - this._centerSpiralCount, 0) / this._sidePanelCount) / Math.sqrt(this._offsetIndex); - }, - - animate: function() - { - var progress = this._benchmark.timestamp % 10000 / 10000; - var bounceProgress = Math.sin(2 * Math.abs( 0.5 - progress)); - var l = Utilities.lerp(bounceProgress, 20, 50); - var hslPrefix = "hsla(" + Utilities.lerp(progress, 0, 360) + ",100%,"; - - for (var i = 0; i < this._offsetIndex; ++i) { - var tile = this.tiles[i]; - tile.active = true; - tile.element.style[tile.visibleCSS[0]] = tile.visibleCSS[2]; - tile.rotate += tile.step; - tile.element.style.transform = "rotate(" + tile.rotate + "deg)"; - - var influence = Math.max(.01, 1 - (tile.distance * this._distanceFactor)); - tile.element.style.backgroundColor = hslPrefix + l * Math.tan(influence / 1.25) + "%," + influence + ")"; - } - - for (var i = this._offsetIndex; i < this.tiles.length && this.tiles[i].active; ++i) { - var tile = this.tiles[i]; - tile.active = false; - tile.element.style[tile.visibleCSS[0]] = tile.visibleCSS[1]; - } + +class Tile { + stage; + coordinate; + roundedRect; + distance; + step; + rotate; + + constructor(stage, coordinate) { + this.stage = stage; + this.coordinate = coordinate; + + this.roundedRect = document.createHTMLElement('div', { + class: "div-" + Random.integer(0, 5) + }, stage.element); + + this.distance = this.coordinate.length(); + this.step = Math.max(3, this.distance / 1.5); + this.rotate = Random.integer(0, 359); + + this.move(); + this.resize(); + this.hide(); + } + + move() { + let tileSize = this.stage.tileSize; + + let location = new Point(this.stage.rect.center()); + location.add(this.coordinate.scaled(tileSize)); + location.subtract(tileSize.scaled(0.5)); + + this.roundedRect.style.left = location.x + 'px'; + this.roundedRect.style.top = location.y + 'px'; + } + + resize() { + let tileSize = this.stage.tileSize; + + this.roundedRect.style.width = tileSize.width + 'px'; + this.roundedRect.style.height = tileSize.height + 'px'; + } + + show() { + this.roundedRect.style.display = "block"; + } + + hide() { + this.roundedRect.style.display = "none"; + } + + backgroundColor() { + let influence = Math.max(.01, 1 - (this.distance * this.stage.distanceFactor)); + let l = this.stage.l * Math.tan(influence); + return this.stage.hslPrefix + l + "%," + influence + ")"; } -}); -var MultiplyBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new MultiplyStage(), options); + animate(timestamp, lastFrameLength) { + this.rotate += this.step; + this.roundedRect.style.transform = "rotate(" + this.rotate + "deg)"; + this.roundedRect.style.backgroundColor = this.backgroundColor(); } -); +} -window.benchmarkClass = MultiplyBenchmark; +class TilesStage extends ReusableParticlesStage { + static rowsCount = 69; + tileSize; + tileGrid; + iterator; + distanceFactor; + + constructor() { + super(); + + let tileSide = Math.floor(this.size.height / TilesStage.rowsCount); + this.tileSize = new Size(tileSide, tileSide); + + let columnsCount = Math.floor(this.size.width / tileSide); + if (columnsCount % 2 == 0) + --columnsCount; + + this.tileGrid = new Size(columnsCount, TilesStage.rowsCount); + this.iterator = new SpiralIterator(this.tileGrid); + + while (!this.iterator.isDone()) + this.particles.push(this.createParticle()); + } + + createParticle() { + if (this.iterator.isDone()) + this.iterator = new SpiralIterator(this.tileGrid); + let tile = new Tile(this, this.iterator.current); + this.iterator.next(); + return tile; + } + + tune(count) { + super.tune(count); + let centerSpiralCount = this.tileGrid.height * this.tileGrid.height; + let sidePanelCount = this.tileGrid.area() - centerSpiralCount; + let activeSidePanelCount = Math.max(this.activeLength - centerSpiralCount, 0); + this.distanceFactor = 1.5 * (1 - 0.5 * activeSidePanelCount / sidePanelCount) / Math.sqrt(this.activeLength); + } + + animate(timestamp, lastFrameLength) { + let progress = timestamp % 10000 / 10000; + let bounceProgress = Math.sin(2 * Math.abs(0.5 - progress)); + this.l = Math.lerp(bounceProgress, 20, 50); + this.hslPrefix = "hsla(" + Math.lerp(progress, 0, 360) + ",100%,"; + super.animate(timestamp, lastFrameLength); + } +} + +class TilesAnimator extends Animator { + constructor(test, settings) { + super(new TilesStage(), test, settings); + } +} -}()); +window.animatorClass = TilesAnimator; diff --git a/MotionMark/tests/core/resources/particles.js b/MotionMark/tests/core/resources/particles.js deleted file mode 100644 index e918e1e..0000000 --- a/MotionMark/tests/core/resources/particles.js +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -function Particle(stage) -{ - this.stage = stage; - this.rotater = Stage.randomRotater(); - this.reset(); - this.move(); -} - -Particle.prototype = -{ - sizeMinimum: 40, - sizeRange: 10, - - reset: function() - { - var randSize = Math.round(Math.pow(Pseudo.random(), 4) * this.sizeRange + this.sizeMinimum); - this.size = new Point(randSize, randSize); - this.minPosition = this.size.center; - this.maxPosition = this.stage.size.subtract(this.minPosition); - }, - - animate: function(timeDelta) - { - this.rotater.next(timeDelta); - - this.position = this.position.add(this.velocity.multiply(timeDelta)); - this.velocity.y += 0.03; - - // If particle is going to move off right side - if (this.position.x > this.maxPosition.x) { - if (this.velocity.x > 0) - this.velocity.x *= -1; - this.position.x = this.maxPosition.x; - } else if (this.position.x < this.minPosition.x) { - // If particle is going to move off left side - if (this.velocity.x < 0) - this.velocity.x *= -1; - this.position.x = this.minPosition.x; - } - - // If particle is going to move off bottom side - if (this.position.y > this.maxPosition.y) { - // Adjust direction but maintain magnitude - var magnitude = this.velocity.length(); - this.velocity.x *= 1.5 + .005 * this.size.x; - this.velocity = this.velocity.normalize().multiply(magnitude); - if (Math.abs(this.velocity.y) < 0.7) - this.reset(); - else { - if (this.velocity.y > 0) - this.velocity.y *= -0.999; - this.position.y = this.maxPosition.y; - } - } else if (this.position.y < this.minPosition.y) { - // If particle is going to move off top side - var magnitude = this.velocity.length(); - this.velocity.x *= 1.5 + .005 * this.size.x; - this.velocity = this.velocity.normalize().multiply(magnitude); - if (this.velocity.y < 0) - this.velocity.y *= -0.998; - this.position.y = this.minPosition.y; - } - - this.move(); - }, - - move: function() - { - } -} - -ParticlesStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - this.particles = []; - }, { - - animate: function(timeDelta) - { - timeDelta /= 4; - this.particles.forEach(function(particle) { - particle.animate(timeDelta); - }); - }, - - tune: function(count) - { - if (count == 0) - return; - - if (count > 0) { - for (var i = 0; i < count; ++i) - this.particles.push(this.createParticle()); - return; - } - - count = Math.min(-count, this.particles.length); - - if (typeof(this.willRemoveParticle) == "function") { - for (var i = 0; i < count; ++i) - this.willRemoveParticle(this.particles[i]); - } - - this.particles.splice(0, count); - }, - - complexity: function() - { - return this.particles.length; - } -}); diff --git a/MotionMark/tests/core/resources/paths.js b/MotionMark/tests/core/resources/paths.js new file mode 100644 index 0000000..a7c2da5 --- /dev/null +++ b/MotionMark/tests/core/resources/paths.js @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +class CanvasSegment { + static strokeColors = [ + "#101010", + "#808080", + "#c0c0c0", + "#101010", + "#808080", + "#c0c0c0", + "#e01040" + ]; + strokeColor; + lineWidth; + isSplit; + + constructor() { + this.strokeColor = Random.itemInArray(CanvasSegment.strokeColors); + this.lineWidth = Math.pow(Pseudo.random(), 5) * 20 + 1; + this.isSplit = Pseudo.random() > 0.5; + } +} + +class CanvasLineToSegment extends CanvasSegment { + point; + + constructor(stage) { + super(); + this.point = stage.randomPoint(); + } + + draw(context) { + context.lineTo(this.point.x, this.point.y); + } +} + +class CanvasQuadraticSegment extends CanvasSegment { + controlPoint; + endPoint; + + constructor(stage) { + super(); + this.controlPoint = stage.randomPoint(); + this.endPoint = stage.randomPoint(); + } + + draw(context) { + context.quadraticCurveTo(this.controlPoint.x, this.controlPoint.y, this.endPoint.x, this.endPoint.y); + } +} + +class CanvasBezierSegment extends CanvasSegment { + controlPoint1; + controlPoint2; + endPoint; + + constructor(stage) { + super(); + this.controlPoint1 = stage.randomPoint(); + this.controlPoint2 = stage.randomPoint(); + this.endPoint = stage.randomPoint(); + } + + draw(context) { + context.bezierCurveTo(this.controlPoint1.x, this.controlPoint1.y, this.controlPoint2.x, this.controlPoint2.y, this.endPoint.x, this.endPoint.y); + } +} + +class PathsStage extends ReusableSegmentsStage { + segmentClasses = [ + CanvasLineToSegment, + CanvasQuadraticSegment, + CanvasBezierSegment + ]; + + gridSize = new Size(80, 40); + offsets = [ + new Point(-4, 0), + new Point(2, 0), + new Point(1, -2), + new Point(1, 2), + ]; + + coordinate; + + constructor() { + super(); + + let context = this.context; + context.lineJoin = "bevel"; + context.lineCap = "butt"; + + this.coordinate = new Point(this.gridSize.width / 2, this.gridSize.height / 2); + } + + randomPoint() { + let offset = Random.itemInArray(this.offsets); + + this.coordinate.add(offset); + if (this.coordinate.x < 0 || this.coordinate.x > this.gridSize.width) + this.coordinate.x -= offset.x * 2; + + if (this.coordinate.y < 0 || this.coordinate.y > this.gridSize.height) + this.coordinate.y -= offset.y * 2; + + let x = (this.coordinate.x + .5) * this.size.width / (this.gridSize.width + 1); + let y = (this.coordinate.y + .5) * this.size.height / (this.gridSize.height + 1); + + return new Point(x, y); + } + + createSegment() { + let segmentClass = Random.itemInArray(this.segmentClasses); + return new segmentClass(this); + } + + beginPath(segment) { + let context = this.context; + context.lineWidth = segment.lineWidth; + context.strokeStyle = segment.strokeColor; + context.beginPath(); + } + + animate() { + let context = this.context; + context.clearRect(0, 0, this.size.width, this.size.height); + + let center = this.rect.center(); + context.beginPath(); + context.moveTo(center.x, center.y); + + for (let segment of this.activeSegments()) { + if (segment.isSplit) { + context.stroke(); + this.beginPath(segment); + } + + segment.draw(context); + + if (Pseudo.random() > 0.995) + segment.isSplit = !segment.isSplit; + } + + context.stroke(); + } +} + +class PathsAnimator extends Animator { + constructor(test, settings) { + super(new PathsStage(), test, settings); + } +} + +window.animatorClass = PathsAnimator; diff --git a/MotionMark/tests/core/resources/performance.svg b/MotionMark/tests/core/resources/performance.svg deleted file mode 100644 index 37c4e95..0000000 --- a/MotionMark/tests/core/resources/performance.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/script.svg b/MotionMark/tests/core/resources/script.svg deleted file mode 100644 index 5e3f9c1..0000000 --- a/MotionMark/tests/core/resources/script.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MotionMark/tests/core/resources/shortcuts.svg b/MotionMark/tests/core/resources/shortcuts.svg deleted file mode 100644 index edaa849..0000000 --- a/MotionMark/tests/core/resources/shortcuts.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MotionMark/tests/core/resources/standards.svg b/MotionMark/tests/core/resources/standards.svg deleted file mode 100644 index ac1e693..0000000 --- a/MotionMark/tests/core/resources/standards.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/resources/storage.svg b/MotionMark/tests/core/resources/storage.svg deleted file mode 100644 index c34a9ed..0000000 --- a/MotionMark/tests/core/resources/storage.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MotionMark/tests/core/resources/styles.svg b/MotionMark/tests/core/resources/styles.svg deleted file mode 100644 index f50cff7..0000000 --- a/MotionMark/tests/core/resources/styles.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MotionMark/tests/core/resources/suits.js b/MotionMark/tests/core/resources/suits.js index 526f879..494dded 100644 --- a/MotionMark/tests/core/resources/suits.js +++ b/MotionMark/tests/core/resources/suits.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 Apple Inc. All rights reserved. + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,126 +22,177 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -(function() { - -window.SuitsParticle = Utilities.createSubclass(Particle, - function(stage) - { - this.isClipPath = stage.particleCounter % 2; - this.initialize(stage); - }, { - - sizeMinimum: 30, - sizeRange: 40, - hasGradient: true, - - initialize: function(stage) - { - var shapeId = "#shape-" + Stage.randomInt(1, stage.particleTypeCount); + +class Suit extends ResettableParticle { + static sideMinimum = 30; + static sideMaximum = 70; + static shapeCounter = 0; + static gradientCounter = 0; + isClipPath; + shape; + gradient; + transformSuffix; + position; + velocity; + + constructor(stage) { + super(stage, Suit.sideMinimum, Suit.sideMaximum); + + this.isClipPath = ++stage.shapeCounter % 2; + + this.createShape(); + this.createGradient(); + + // Move it to some initial position. + this.reset(); + this.move(0); + } + + createShape() { + var shapeId = "#shape-" + Random.integer(1, this.stage.shapesCount); + if (this.isClipPath) { - this.element = Utilities.createSVGElement("rect", { - x: 0, - y: 0, + this.shape = document.createSVGElement("rect", { "clip-path": "url(" + shapeId + ")" - }, {}, stage.element); + }, this.stage.element); } else { var shapePath = document.querySelector(shapeId + " path"); - this.element = shapePath.cloneNode(); - stage.element.appendChild(this.element); + this.shape = shapePath.cloneNode(); + this.stage.element.appendChild(this.shape); } + } - if (this.hasGradient) { - this.gradient = document.getElementById("default-gradient").cloneNode(true); - this.gradient.id = "gradient-" + stage.gradientsCounter++; - stage.gradientsDefs.appendChild(this.gradient); - this.element.setAttribute("fill", "url(#" + this.gradient.id + ")"); - } - Particle.call(this, stage); - }, + createGradient() { + this.gradient = this.stage.defaultGradient.cloneNode(true); + this.gradient.id = "gradient-" + Suit.gradientCounter++; + this.stage.gradientsDefs.appendChild(this.gradient); + this.shape.setAttribute("fill", "url(#" + this.gradient.id + ")"); + } - reset: function() - { - Particle.prototype.reset.call(this); + resetShape() { + if (this.isClipPath) { + this.shape.setAttribute("width", this.size.width); + this.shape.setAttribute("height", this.size.height); + this.transformSuffix = " translate(-" + (this.size.width / 2) + ",-" + (this.size.height / 2) + ")"; + } else + this.transformSuffix = " scale(" + this.size.width + ") translate(-.5,-.5)"; + } - this.position = Stage.randomElementInArray(this.stage.emitLocation); + resetGradient() { + let transform = this.stage.element.createSVGTransform(); + transform.setRotate(Random.integer(0, 359), 0, 0); + this.gradient.gradientTransform.baseVal.initialize(transform); - var velocityMagnitude = Stage.random(.5, 2.5); - var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(1000) * this.stage.emissionSpin + velocityMagnitude; - this.velocity = new Point(Math.sin(angle), Math.cos(angle)) - .multiply(velocityMagnitude); + let stops = this.gradient.querySelectorAll("stop"); + stops[0].setAttribute("stop-color", "hsl(" + this.stage.colorOffset + ", 70%, 45%)"); + stops[1].setAttribute("stop-color", "hsl(" + ((this.stage.colorOffset + Random.integer(50,100)) % 360) + ", 70%, 65%)"); + } - if (this.isClipPath) { - this.element.setAttribute("width", this.size.x); - this.element.setAttribute("height", this.size.y); - this.transformSuffix = " translate(-" + this.size.center.x + ",-" + this.size.center.y + ")"; - } else - this.transformSuffix = " scale(" + this.size.x + ") translate(-.5,-.5)"; + reset() { + super.reset(); + + this.position = new Point(Random.itemInArray(this.stage.emitLocations)); + + var velocityMagnitude = Random.number(.5, 2.5); + var angle = Random.integer(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Random.dateCounterValue(1000) * this.stage.emissionSpin + velocityMagnitude; + this.velocity = new Point(Math.sin(angle) * velocityMagnitude, Math.cos(angle) * velocityMagnitude); this.stage.colorOffset = (this.stage.colorOffset + .5) % 360; - if (this.hasGradient) { - var transform = this.stage.element.createSVGTransform(); - transform.setRotate(Stage.randomInt(0, 359), 0, 0); - this.gradient.gradientTransform.baseVal.initialize(transform); + this.resetShape(); + this.resetGradient(); + } - var stops = this.gradient.querySelectorAll("stop"); - stops[0].setAttribute("stop-color", "hsl(" + this.stage.colorOffset + ", 70%, 45%)"); - stops[1].setAttribute("stop-color", "hsl(" + ((this.stage.colorOffset + Stage.randomInt(50,100)) % 360) + ", 70%, 65%)"); - } else - this.element.setAttribute("fill", "hsl(" + this.stage.colorOffset + ", 70%, 65%)"); - }, + move(timestamp) { + this.shape.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.rotator.rotate(timestamp, Point.zero()) + this.transformSuffix); + } + + animate(timestamp, lastFrameLength) { + let timeDelta = lastFrameLength / 4; + + this.position.add(this.velocity.scaled(timeDelta)); + this.velocity.y += 0.03; + + // If particle is going to move off right side + if (this.position.x > this.bouncingRect.maxX) { + if (this.velocity.x > 0) + this.velocity.x *= -1; + this.position.x = this.bouncingRect.maxX; + } else if (this.position.x < this.bouncingRect.x) { + // If particle is going to move off left side + if (this.velocity.x < 0) + this.velocity.x *= -1; + this.position.x = this.bouncingRect.x; + } + + // If particle is going to move off bottom side + if (this.position.y > this.bouncingRect.maxY) { + // Adjust direction but maintain magnitude + var magnitude = this.velocity.length(); + this.velocity.x *= 1.5 + .005 * this.size.width; + this.velocity = this.velocity.normalized().scaled(magnitude); + if (Math.abs(this.velocity.y) < 0.7) + this.reset(); + else { + if (this.velocity.y > 0) + this.velocity.y *= -0.999; + this.position.y = this.bouncingRect.maxY; + } + } else if (this.position.y < this.bouncingRect.y) { + // If particle is going to move off top side + var magnitude = this.velocity.length(); + this.velocity.x *= 1.5 + .005 * this.size.width; + this.velocity = this.velocity.normalized().scaled(magnitude); + if (this.velocity.y < 0) + this.velocity.y *= -0.998; + this.position.y = this.bouncingRect.y; + } - move: function() - { - this.element.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.rotater.rotate(Point.zero) + this.transformSuffix); + this.move(timestamp); } -}); - -var SuitsStage = Utilities.createSubclass(ParticlesStage, - function() - { - ParticlesStage.call(this); - }, { - - initialize: function(benchmark) - { - ParticlesStage.prototype.initialize.call(this, benchmark); - this.emissionSpin = Stage.random(0, 3); - this.emitSteps = Stage.randomInt(4, 6); - this.emitLocation = [ - new Point(this.size.x * .25, this.size.y * .333), - new Point(this.size.x * .5, this.size.y * .25), - new Point(this.size.x * .75, this.size.y * .333) - ]; - this.colorOffset = Stage.randomInt(0, 359); +} + +class SuitsStage extends DisposableParticlesStage { + gradientsDefs; + defaultGradient; + shapesCount; + emissionSpin; + emitSteps; + emitLocations; + colorOffset; + + constructor() { + super(); - this.particleTypeCount = document.querySelectorAll(".shape").length; this.gradientsDefs = document.getElementById("gradients"); - this.gradientsCounter = 0; - this.particleCounter = 0; - }, - - createParticle: function() - { - this.particleCounter++; - return new SuitsParticle(this); - }, - - willRemoveParticle: function(particle) - { - particle.element.remove(); - if (particle.gradient) - particle.gradient.remove(); + this.defaultGradient = document.getElementById("default-gradient"); + this.shapesCount = document.querySelectorAll(".shape").length; + + this.emissionSpin = Random.number(0, 3); + this.emitSteps = Random.integer(4, 6); + this.emitLocations = [ + new Point(this.size.width * .25, this.size.height * .333), + new Point(this.size.width * .50, this.size.height * .250), + new Point(this.size.width * .75, this.size.height * .333) + ]; + + this.colorOffset = Random.integer(0, 359); } -}); -var SuitsBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new SuitsStage(), options); + createParticle() { + return new Suit(this); } -); -window.benchmarkClass = SuitsBenchmark; + removeParticle(suit) { + suit.shape.remove(); + suit.gradient.remove(); + } +} + +class SuitsAnimator extends Animator { + constructor(test, settings) { + super(new SuitsStage(), test, settings); + } +} -})(); +window.animatorClass = SuitsAnimator; diff --git a/MotionMark/tests/core/resources/timeline.svg b/MotionMark/tests/core/resources/timeline.svg deleted file mode 100644 index cd1e8a4..0000000 --- a/MotionMark/tests/core/resources/timeline.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/MotionMark/tests/core/shared/disposable-particles.js b/MotionMark/tests/core/shared/disposable-particles.js new file mode 100644 index 0000000..986ac3e --- /dev/null +++ b/MotionMark/tests/core/shared/disposable-particles.js @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +class DisposableParticlesStage extends Stage { + particles; + + constructor() { + super(); + this.particles = []; + } + + complexity() { + return this.particles.length; + } + + tune(count) { + if (count == 0) + return; + + if (count > 0) { + for (var i = 0; i < count; ++i) + this.particles.push(this.createParticle()); + return; + } + + count = Math.min(-count, this.particles.length); + + for (var i = 0; i < count; ++i) + this.removeParticle(this.particles[i]); + + this.particles.splice(0, count); + } + + animate(timestamp, lastFrameLength) { + for (let particle of this.particles) + particle.animate(timestamp, lastFrameLength); + } +} diff --git a/MotionMark/tests/core/shared/resettable-particle.js b/MotionMark/tests/core/shared/resettable-particle.js new file mode 100644 index 0000000..614e33b --- /dev/null +++ b/MotionMark/tests/core/shared/resettable-particle.js @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +class ResettableParticle { + stage; + sizeRange; + size; + bouncingRect; + rotator; + + constructor(stage, sideMinimum, sideMaximum) { + this.stage = stage; + this.sizeRange = new Range(sideMinimum, sideMaximum - sideMinimum); + } + + reset() { + let side = Math.round(this.sizeRange.start + Math.pow(Pseudo.random(), 4) * this.sizeRange.length); + this.size = new Size(side, side); + + this.bouncingRect = new Rect(this.stage.rect); + this.bouncingRect.inflate(-side / 2); + + this.rotator = Random.rotator(1000, 10000); + } +} diff --git a/MotionMark/tests/core/shared/reusable-particles.js b/MotionMark/tests/core/shared/reusable-particles.js new file mode 100644 index 0000000..2de38c4 --- /dev/null +++ b/MotionMark/tests/core/shared/reusable-particles.js @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +class ReusableParticlesStage extends Stage { + particles; + activeLength; + + constructor() { + super(); + this.particles = []; + this.activeLength = 0; + } + + complexity() { + return this.activeLength; + } + + activeParticles() { + return this.particles.slice(0, this.activeLength); + } + + inactiveParticles(end) { + return this.particles.slice(this.activeLength, end); + } + + tune(count) { + if (count == 0) + return; + + if (count < 0) { + this.activeLength = Math.max(this.activeLength + count, 0); + for (var i = this.activeLength; i < this.particles.length; ++i) + this.particles[i].hide(); + return; + } + + let inactiveParticles = this.inactiveParticles(this.activeLength + count); + for (let particle of inactiveParticles) + particle.show(); + + for (let i = inactiveParticles.length; i < count; ++i) + this.particles.push(this.createParticle()); + + this.activeLength += count; + } + + animate(timestamp, lastFrameLength) { + for (let particle of this.activeParticles()) + particle.animate(timestamp, lastFrameLength); + } +} diff --git a/MotionMark/tests/simple/resources/simple-canvas.js b/MotionMark/tests/core/shared/reusable-segments.js similarity index 54% rename from MotionMark/tests/simple/resources/simple-canvas.js rename to MotionMark/tests/core/shared/reusable-segments.js index b3810e1..ad867b7 100644 --- a/MotionMark/tests/simple/resources/simple-canvas.js +++ b/MotionMark/tests/core/shared/reusable-segments.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * Copyright (C) 2015-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,38 +22,44 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -Utilities.extendObject(SimpleCanvasStage.prototype, { - tune: function(count) - { + +class ReusableSegmentsStage extends Stage { + segments; + inactiveLength; + context; + + constructor() { + super(); + this.segments = []; + this.inactiveLength = 0; + this.context = this.element.getContext("2d"); + } + + get activeLength() { + return this.segments.length - this.inactiveLength; + } + + complexity() { + return this.activeLength; + } + + activeSegments() { + return this.segments.slice(this.inactiveLength, this.segments.length); + } + + tune(count) { if (count == 0) return; if (count < 0) { - this.offsetIndex = Math.max(this.offsetIndex + count, 0); + this.inactiveLength = Math.min(this.inactiveLength - count, this.segments.length); return; } - this.offsetIndex = this.offsetIndex + count; - if (this.offsetIndex > this.objects.length) { - // For some tests, it may be easier to see how well the test is going - // by limiting the range of coordinates in which new objects can reside - var coordinateMaximumFactor = Math.min(this.objects.length, Math.min(this.size.x, this.size.y)) / Math.min(this.size.x, this.size.y); - var newIndex = this.offsetIndex - this.objects.length; - for (var i = 0; i < newIndex; ++i) - this.objects.push(new this._canvasObject(this, coordinateMaximumFactor)); - } - }, - - animate: function() - { - var context = this.context; - context.clearRect(0, 0, this.size.x, this.size.y); - for (var i = 0, length = this.offsetIndex; i < length; ++i) - this.objects[i].draw(context); - }, - - complexity: function() - { - return this.offsetIndex; + let inactiveLength = Math.min(this.inactiveLength, count); + for (let i = inactiveLength; i < count; ++i) + this.segments.push(this.createSegment()); + + this.inactiveLength -= inactiveLength; } -}); +} diff --git a/MotionMark/tests/core/suits.html b/MotionMark/tests/core/suits.html index 72d0872..85b9c28 100644 --- a/MotionMark/tests/core/suits.html +++ b/MotionMark/tests/core/suits.html @@ -1,5 +1,5 @@ - - - - - - - - -
- - - - - - - - - diff --git a/MotionMark/tests/dom/focus.html b/MotionMark/tests/dom/focus.html deleted file mode 100644 index cef614e..0000000 --- a/MotionMark/tests/dom/focus.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - -
-
focus
-
- - - - - - - - diff --git a/MotionMark/tests/dom/multiply.html b/MotionMark/tests/dom/multiply.html deleted file mode 100644 index b5bef91..0000000 --- a/MotionMark/tests/dom/multiply.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - -
-
- - - - - - - - - diff --git a/MotionMark/tests/dom/particles.html b/MotionMark/tests/dom/particles.html deleted file mode 100644 index 02b0786..0000000 --- a/MotionMark/tests/dom/particles.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - -
- - - - - - - - - diff --git a/MotionMark/tests/dom/resources/compositing-transforms.js b/MotionMark/tests/dom/resources/compositing-transforms.js deleted file mode 100644 index c92fadf..0000000 --- a/MotionMark/tests/dom/resources/compositing-transforms.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -BouncingCompositedImage = Utilities.createSubclass(BouncingParticle, - function(stage) - { - BouncingParticle.call(this, stage); - - this.element = document.createElement("img"); - this.element.style.width = this.size.x + "px"; - this.element.style.height = this.size.y + "px"; - this.element.setAttribute("src", stage.imageSrc); - - if (stage.useFilters) - this.element.style.filter = "hue-rotate(" + Stage.randomAngle() + "rad)"; - - stage.element.appendChild(this.element); - this._move(); - }, { - - _move: function() - { - this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) " + this.rotater.rotateZ(); - }, - - animate: function(timeDelta) - { - BouncingParticle.prototype.animate.call(this, timeDelta); - this._move(); - } -}); - -CompositingTransformsStage = Utilities.createSubclass(BouncingParticlesStage, - function() - { - BouncingParticlesStage.call(this); - }, { - - initialize: function(benchmark, options) - { - BouncingParticlesStage.prototype.initialize.call(this, benchmark, options); - - this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg"; - this.useFilters = options["filters"] == "yes"; - }, - - createParticle: function() - { - return new BouncingCompositedImage(this); - }, - - particleWillBeRemoved: function(particle) - { - particle.element.remove(); - } -}); - -CompositedTransformsBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new CompositingTransformsStage(), options); - } -); - -window.benchmarkClass = CompositedTransformsBenchmark; - -})(); diff --git a/MotionMark/tests/dom/resources/dom-particles.js b/MotionMark/tests/dom/resources/dom-particles.js deleted file mode 100644 index 985de3c..0000000 --- a/MotionMark/tests/dom/resources/dom-particles.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -DOMParticle = Utilities.createSubclass(Particle, - function(stage) - { - this.element = document.createElement("div"); - stage.element.appendChild(this.element); - - Particle.call(this, stage); - }, { - - reset: function() - { - Particle.prototype.reset.call(this); - - this.position = Stage.randomElementInArray(this.stage.emitLocation); - - var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(100) * this.stage.emissionSpin; - this.velocity = new Point(Math.sin(angle), Math.cos(angle)) - .multiply(Stage.random(.5, 2.5)); - - this.element.style.width = this.size.x + "px"; - this.element.style.height = this.size.y + "px"; - this.stage.colorOffset = (this.stage.colorOffset + 1) % 360; - this.element.style.backgroundColor = "hsl(" + this.stage.colorOffset + ", 70%, 45%)"; - }, - - move: function() - { - this.element.style.transform = "translate(" + this.position.x + "px, " + this.position.y + "px)" + this.rotater.rotateZ(); - } -}); - -DOMParticleStage = Utilities.createSubclass(ParticlesStage, - function() - { - ParticlesStage.call(this); - }, { - - initialize: function(benchmark) - { - ParticlesStage.prototype.initialize.call(this, benchmark); - this.emissionSpin = Stage.random(0, 3); - this.emitSteps = Stage.randomInt(4, 6); - this.emitLocation = [ - new Point(this.size.x * .25, this.size.y * .333), - new Point(this.size.x * .5, this.size.y * .25), - new Point(this.size.x * .75, this.size.y * .333) - ]; - this.colorOffset = Stage.randomInt(0, 359); - }, - - createParticle: function() - { - return new DOMParticle(this); - }, - - willRemoveParticle: function(particle) - { - particle.element.remove(); - } -}); - -DOMParticleBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new DOMParticleStage(), options); - } -); - -window.benchmarkClass = DOMParticleBenchmark; - -})(); diff --git a/MotionMark/tests/dom/resources/focus.js b/MotionMark/tests/dom/resources/focus.js deleted file mode 100644 index c268d98..0000000 --- a/MotionMark/tests/dom/resources/focus.js +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -var maxVerticalOffset = 50; -var minimumDiameter = 30; -var centerDiameter = 90; -var sizeVariance = 60; -var travelDistance = 50; - -var opacityMultiplier = 30; - -var FocusElement = Utilities.createClass( - function(stage) - { - var size = minimumDiameter + sizeVariance; - - // Size and blurring are a function of depth. - this._depth = Pseudo.random(); - var distance = Utilities.lerp(this._depth, 0, sizeVariance); - size -= distance; - - var top = Stage.random(0, stage.size.height - size) - stage.maxBlurValue * 3; - var left = Stage.random(0, stage.size.width - size) - stage.maxBlurValue * 3; - - this.container = document.createElement('div'); - this.container.style.width = (size + stage.maxBlurValue * 6) + "px"; - this.container.style.height = (size + stage.maxBlurValue * 6) + "px"; - this.container.style.top = top + "px"; - this.container.style.left = left + "px"; - this.container.style.zIndex = Math.round((1 - this._depth) * 10); - - this.particle = Utilities.createElement("div", {}, this.container); - this.particle.style.width = size + "px"; - this.particle.style.height = size + "px"; - this.particle.style.top = (stage.maxBlurValue * 3) + "px"; - this.particle.style.left = (stage.maxBlurValue * 3) + "px"; - - var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1); - this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; - this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance; - }, { - - hide: function() - { - this.container.style.display = "none"; - }, - - show: function() - { - this.container.style.display = "block"; - }, - - animate: function(stage, sinFactor, cosFactor) - { - var top = sinFactor * this._sinMultiplier; - var left = cosFactor * this._cosMultiplier; - - Utilities.setElementPrefixedProperty(this.container, "filter", "blur(" + stage.getBlurValue(this._depth) + "px) opacity(" + stage.getOpacityValue(this._depth) + "%)"); - this.container.style.transform = "translate3d(" + left + "%, " + top + "%, 0)"; - } -}); - -var FocusStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - }, { - - movementDuration: 2500, - focusDuration: 1000, - - centerObjectDepth: 0.0, - - minBlurValue: 1.5, - maxBlurValue: 15, - maxCenterObjectBlurValue: 5, - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - - this._testElements = []; - this._focalPoint = 0.5; - this._offsetIndex = 0; - - this._centerElement = document.getElementById("center-text"); - this._centerElement.style.width = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px"; - this._centerElement.style.height = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px"; - this._centerElement.style.zIndex = Math.round(10 * this.centerObjectDepth); - - var particle = document.querySelector("#center-text div"); - particle.style.width = centerDiameter + "px"; - particle.style.height = centerDiameter + "px"; - particle.style.top = (this.maxCenterObjectBlurValue * 3) + "px"; - particle.style.left = (this.maxCenterObjectBlurValue * 3) + "px"; - - var blur = this.getBlurValue(this.centerObjectDepth, true); - Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + blur + "px)"); - }, - - complexity: function() - { - return 1 + this._offsetIndex; - }, - - tune: function(count) - { - if (count == 0) - return; - - if (count < 0) { - this._offsetIndex = Math.max(0, this._offsetIndex + count); - for (var i = this._offsetIndex; i < this._testElements.length; ++i) - this._testElements[i].hide(); - return; - } - - var newIndex = this._offsetIndex + count; - for (var i = this._testElements.length; i < newIndex; ++i) { - var obj = new FocusElement(this); - this._testElements.push(obj); - this.element.appendChild(obj.container); - } - for (var i = this._offsetIndex; i < newIndex; ++i) - this._testElements[i].show(); - this._offsetIndex = newIndex; - }, - - animate: function() - { - var time = this._benchmark.timestamp; - var sinFactor = Math.sin(time / this.movementDuration); - var cosFactor = Math.cos(time / this.movementDuration); - - var focusProgress = 0.5 + 0.5 * Math.sin(time / this.focusDuration); - this._focalPoint = focusProgress; - - Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + this.getBlurValue(this.centerObjectDepth, true) + "px)"); - - for (var i = 0; i < this._offsetIndex; ++i) - this._testElements[i].animate(this, sinFactor, cosFactor); - }, - - getBlurValue: function(depth, isCenter) - { - if (isCenter) - return 1 + Math.abs(depth - this._focalPoint) * (this.maxCenterObjectBlurValue - 1); - - return Utilities.lerp(Math.abs(depth - this._focalPoint), this.minBlurValue, this.maxBlurValue); - }, - - getOpacityValue: function(depth) - { - return Math.max(1, opacityMultiplier * (1 - Math.abs(depth - this._focalPoint))); - }, -}); - -var FocusBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new FocusStage(), options); - } -); - -window.benchmarkClass = FocusBenchmark; - -}()); diff --git a/MotionMark/tests/dom/resources/leaves.js b/MotionMark/tests/dom/resources/leaves.js deleted file mode 100644 index a0bb633..0000000 --- a/MotionMark/tests/dom/resources/leaves.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2015-2018 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -var SuperLeaf = window.Leaf; -var SimpleLeaf = Utilities.createSubclass(SuperLeaf, - function(stage) - { - SuperLeaf.call(this, stage); - }, { - - sizeMinimum: 25, - sizeRange: 0, - usesOpacity: false, - - move: function() - { - this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); - } -}); - -var ScaleLeaf = Utilities.createSubclass(SuperLeaf, - function(stage) - { - SuperLeaf.call(this, stage); - }, { - - sizeMinimum: 20, - sizeRange: 30, - usesOpacity: false, - - move: function() - { - this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); - } -}); - -var OpacityLeaf = Utilities.createSubclass(SuperLeaf, - function(stage) - { - SuperLeaf.call(this, stage); - }, { - - sizeMinimum: 25, - sizeRange: 0, - usesOpacity: true, - - move: function() - { - this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ(); - this.element.style.opacity = this._opacity; - } -}); - - -var LeavesBenchmark = window.benchmarkClass; -var LeavesDerivedBenchmark = Utilities.createSubclass(LeavesBenchmark, - function(options) - { - switch (options["style"]) { - case "simple": - window.Leaf = SimpleLeaf; - break; - case "scale": - window.Leaf = ScaleLeaf; - break; - case "opacity": - window.Leaf = OpacityLeaf; - break; - } - LeavesBenchmark.call(this, options); - } -); - -window.benchmarkClass = LeavesDerivedBenchmark; - -})(); diff --git a/MotionMark/tests/resources/main.js b/MotionMark/tests/resources/main.js deleted file mode 100644 index ca7f2a9..0000000 --- a/MotionMark/tests/resources/main.js +++ /dev/null @@ -1,998 +0,0 @@ -/* - * Copyright (C) 2015-2021 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -Sampler = Utilities.createClass( - function(seriesCount, expectedSampleCount, processor) - { - this._processor = processor; - - this.samples = []; - for (var i = 0; i < seriesCount; ++i) { - var array = new Array(expectedSampleCount); - array.fill(0); - this.samples[i] = array; - } - this.sampleCount = 0; - }, { - - record: function() - { - // Assume that arguments.length == this.samples.length - for (var i = 0; i < arguments.length; i++) { - this.samples[i][this.sampleCount] = arguments[i]; - } - ++this.sampleCount; - }, - - processSamples: function() - { - var results = {}; - - // Remove unused capacity - this.samples = this.samples.map(function(array) { - return array.slice(0, this.sampleCount); - }, this); - - this._processor.processSamples(results); - - return results; - } -}); - -const sampleTypeIndex = 0; -const sampleTimeIndex = 1; -const sampleComplexityIndex = 2; -const sampleFrameLengthEstimateIndex = 3; - -Controller = Utilities.createClass( - function(benchmark, options) - { - // Initialize timestamps relative to the start of the benchmark - // In start() the timestamps are offset by the start timestamp - this._startTimestamp = 0; - this._endTimestamp = options["test-interval"]; - this._targetFrameRate = options["frame-rate"]; - // Default data series: timestamp, complexity, estimatedFrameLength - var sampleSize = options["sample-capacity"] || (this._targetFrameRate * options["test-interval"] / 1000); - this._sampler = new Sampler(options["series-count"] || 4, sampleSize, this); - this._marks = {}; - - this._frameLengthEstimator = new SimpleKalmanEstimator(options["kalman-process-error"], options["kalman-measurement-error"]); - this._isFrameLengthEstimatorEnabled = true; - - // Length of subsequent intervals; a value of 0 means use no intervals - this.intervalSamplingLength = 100; - - this.initialComplexity = 1; - }, { - - set isFrameLengthEstimatorEnabled(enabled) - { - this._isFrameLengthEstimatorEnabled = enabled; - }, - - start: function(startTimestamp, stage) - { - this._startTimestamp = startTimestamp; - this._endTimestamp += startTimestamp; - this._previousTimestamp = startTimestamp; - this._measureAndResetInterval(startTimestamp); - this.recordFirstSample(startTimestamp, stage); - }, - - recordFirstSample: function(startTimestamp, stage) - { - this._sampler.record(Strings.json.mutationFrameType, startTimestamp, stage.complexity(), -1); - this.mark(Strings.json.samplingStartTimeOffset, startTimestamp); - }, - - mark: function(comment, timestamp, data) - { - data = data || {}; - data.time = timestamp; - data.index = this._sampler.sampleCount; - this._marks[comment] = data; - }, - - containsMark: function(comment) - { - return comment in this._marks; - }, - - filterOutOutliers: function(array) - { - if (array.length == 0) - return []; - - array.sort((a, b) => a - b); - var q1 = array[Math.min(Math.round(array.length * 1 / 4), array.length - 1)]; - var q3 = array[Math.min(Math.round(array.length * 3 / 4), array.length - 1)]; - var interquartileRange = q3 - q1; - var minimum = q1 - interquartileRange * 1.5; - var maximum = q3 + interquartileRange * 1.5; - return array.filter(x => x >= minimum && x <= maximum); - }, - - _measureAndResetInterval: function(currentTimestamp) - { - var sampleCount = this._sampler.sampleCount; - var averageFrameLength = 0; - - if (this._intervalEndTimestamp) { - var durations = []; - for (var i = Math.max(this._intervalStartIndex, 1); i < sampleCount; ++i) { - durations.push(this._sampler.samples[sampleTimeIndex][i] - this._sampler.samples[sampleTimeIndex][i - 1]); - } - var filteredDurations = this.filterOutOutliers(durations); - if (filteredDurations.length > 0) - averageFrameLength = filteredDurations.reduce((a, b) => a + b, 0) / filteredDurations.length; - } - - this._intervalStartIndex = sampleCount; - this._intervalEndTimestamp = currentTimestamp + this.intervalSamplingLength; - - return averageFrameLength; - }, - - _getFrameType: function(samples, i) - { - return samples[sampleTypeIndex][i]; - }, - - _getComplexity: function(samples, i) - { - return samples[sampleComplexityIndex][i]; - }, - - _getFrameLength: function(samples, i) - { - return samples[sampleTimeIndex][i] - samples[sampleTimeIndex][i - 1]; - }, - - _previousFrameComplexity: function(samples, i) - { - if (i > 0) - return this._getComplexity(samples, i - 1); - - return 0; - }, - - update: function(timestamp, stage) - { - const frameType = this._previousFrameComplexity(this._sampler.samples, this._sampler.sampleCount) != stage.complexity() ? Strings.json.mutationFrameType : Strings.json.animationFrameType - var lastFrameLength = timestamp - this._previousTimestamp; - this._previousTimestamp = timestamp; - - var frameLengthEstimate = -1, intervalAverageFrameLength = -1; - var didFinishInterval = false; - if (!this.intervalSamplingLength) { - if (this._isFrameLengthEstimatorEnabled) { - this._frameLengthEstimator.sample(lastFrameLength); - frameLengthEstimate = this._frameLengthEstimator.estimate; - } - this._sampler.record(frameType, timestamp, stage.complexity(), frameLengthEstimate); - } else { - this.registerFrameTime(lastFrameLength); - if (this.intervalHasConcluded(timestamp)) { - var intervalStartTimestamp = this._sampler.samples[sampleTimeIndex][this._intervalStartIndex]; - intervalAverageFrameLength = this._measureAndResetInterval(timestamp); - if (this._isFrameLengthEstimatorEnabled) { - this._frameLengthEstimator.sample(intervalAverageFrameLength); - frameLengthEstimate = this._frameLengthEstimator.estimate; - } - this._sampler.record(frameType, timestamp, stage.complexity(), frameLengthEstimate); - - didFinishInterval = true; - this.didFinishInterval(timestamp, stage, intervalAverageFrameLength); - this._frameLengthEstimator.reset(); - } else - this._sampler.record(frameType, timestamp, stage.complexity(), frameLengthEstimate); - } - - this.tune(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength); - }, - - registerFrameTime: function(lastFrameLength) - { - }, - - intervalHasConcluded: function(timestamp) - { - return timestamp >= this._intervalEndTimestamp; - }, - - didFinishInterval: function(timestamp, stage, intervalAverageFrameLength) - { - }, - - tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength) - { - }, - - shouldStop: function(timestamp) - { - return timestamp > this._endTimestamp; - }, - - results: function() - { - return this._sampler.processSamples(); - }, - - _processComplexitySamples: function(complexitySamples) - { - complexitySamples.sort(function(a, b) { - return complexitySamples.getFieldInDatum(a, Strings.json.complexity) - complexitySamples.getFieldInDatum(b, Strings.json.complexity); - }); - }, - - _processMarks: function() - { - for (var markName in this._marks) - this._marks[markName].time -= this._startTimestamp; - return this._marks; - }, - - _processControllerSamples: function() - { - const processedSampleTypeIndex = 0; - const processedSampleTimeIndex = 1; - const processedSampleComplexityIndex = 2; - const processedSampleFrameLengthIndex = 3; - const processedSampleSmoothedFrameLengthIndex = 4; - - var controllerSamples = new SampleData; - controllerSamples.addField(Strings.json.frameType, processedSampleTypeIndex); - controllerSamples.addField(Strings.json.time, processedSampleTimeIndex); - controllerSamples.addField(Strings.json.complexity, processedSampleComplexityIndex); - - controllerSamples.addField(Strings.json.frameLength, processedSampleFrameLengthIndex); - controllerSamples.addField(Strings.json.smoothedFrameLength, processedSampleSmoothedFrameLengthIndex); - - var samples = this._sampler.samples; - samples[sampleTimeIndex].forEach(function(timestamp, i) { - var sample = controllerSamples.createDatum(); - controllerSamples.push(sample); - - // Represent time in milliseconds - controllerSamples.setFieldInDatum(sample, Strings.json.frameType, samples[sampleTypeIndex][i]); - controllerSamples.setFieldInDatum(sample, Strings.json.time, timestamp - this._startTimestamp); - controllerSamples.setFieldInDatum(sample, Strings.json.complexity, samples[sampleComplexityIndex][i]); - - if (i == 0) - controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, 1000/this._targetFrameRate); - else - controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, timestamp - samples[sampleTimeIndex][i - 1]); - - if (samples[sampleFrameLengthEstimateIndex][i] != -1) - controllerSamples.setFieldInDatum(sample, Strings.json.smoothedFrameLength, samples[sampleFrameLengthEstimateIndex][i]); - }, this); - - return controllerSamples; - }, - - processSamples: function(results) - { - results[Strings.json.marks] = this._processMarks(); - - var controllerSamples = this._processControllerSamples(); - var complexitySamples = new SampleData(controllerSamples.fieldMap); - - results[Strings.json.samples] = {}; - results[Strings.json.samples][Strings.json.controller] = controllerSamples; - results[Strings.json.samples][Strings.json.complexity] = complexitySamples; - controllerSamples.forEach(function (sample) { - complexitySamples.push(sample); - }); - this._processComplexitySamples(complexitySamples); - } -}); - -FixedController = Utilities.createSubclass(Controller, - function(benchmark, options) - { - Controller.call(this, benchmark, options); - this.initialComplexity = options["complexity"]; - this.intervalSamplingLength = 0; - } -); - -AdaptiveController = Utilities.createSubclass(Controller, - function(benchmark, options) - { - // Data series: timestamp, complexity, estimatedIntervalFrameLength - Controller.call(this, benchmark, options); - - // All tests start at 0, so we expect to see the target fps quickly. - this._samplingTimestamp = options["test-interval"] / 2; - this._startedSampling = false; - this._targetFrameRate = options["frame-rate"]; - this._pid = new PIDController(this._targetFrameRate); - - this._intervalFrameCount = 0; - this._numberOfFramesToMeasurePerInterval = 4; - }, { - - start: function(startTimestamp, stage) - { - Controller.prototype.start.call(this, startTimestamp, stage); - - this._samplingTimestamp += startTimestamp; - this._intervalTimestamp = startTimestamp; - }, - - recordFirstSample: function(startTimestamp, stage) - { - this._sampler.record(Strings.json.mutationFrameType, startTimestamp, stage.complexity(), -1); - }, - - update: function(timestamp, stage) - { - if (!this._startedSampling && timestamp >= this._samplingTimestamp) { - this._startedSampling = true; - this.mark(Strings.json.samplingStartTimeOffset, this._samplingTimestamp); - } - - // Start the work for the next frame. - ++this._intervalFrameCount; - - if (this._intervalFrameCount < this._numberOfFramesToMeasurePerInterval) { - this._sampler.record(Strings.json.animationFrameType, timestamp, stage.complexity(), -1); - return; - } - - // Adjust the test to reach the desired FPS. - var intervalLength = timestamp - this._intervalTimestamp; - this._frameLengthEstimator.sample(intervalLength / this._numberOfFramesToMeasurePerInterval); - var intervalEstimatedFrameRate = 1000 / this._frameLengthEstimator.estimate; - var tuneValue = -this._pid.tune(timestamp - this._startTimestamp, intervalLength, intervalEstimatedFrameRate); - tuneValue = tuneValue > 0 ? Math.floor(tuneValue) : Math.ceil(tuneValue); - stage.tune(tuneValue); - - this._sampler.record(Strings.json.mutationFrameType, timestamp, stage.complexity(), this._frameLengthEstimator.estimate); - - // Start the next interval. - this._intervalFrameCount = 0; - this._intervalTimestamp = timestamp; - } -}); - -RampController = Utilities.createSubclass(Controller, - function(benchmark, options) - { - this.targetFPS = options["frame-rate"]; - - // The tier warmup takes at most 5 seconds - options["sample-capacity"] = (options["test-interval"] / 1000 + 5) * this.targetFPS; - Controller.call(this, benchmark, options); - - // Initially start with a tier test to find the bounds - // The number of objects in a tier test is 10^|_tier| - this._tier = -.5; - // The timestamp is first set after the first interval completes - this._tierStartTimestamp = 0; - this._minimumComplexity = 1; - this._maximumComplexity = 1; - - this._testLength = options["test-interval"]; - - // After the tier range is determined, figure out the number of ramp iterations - var minimumRampLength = 3000; - var totalRampIterations = Math.max(1, Math.floor(this._endTimestamp / minimumRampLength)); - // Give a little extra room to run since the ramps won't be exactly this length - this._rampLength = Math.floor((this._endTimestamp - totalRampIterations * this.intervalSamplingLength) / totalRampIterations); - this._rampDidWarmup = false; - this._rampRegressions = []; - - this._finishedTierSampling = false; - this._changePointEstimator = new Experiment; - this._minimumComplexityEstimator = new Experiment; - // Estimates all frames within an interval - this._intervalFrameLengthEstimator = new Experiment; - - // Used for regression calculations in the ramps - this.frameLengthDesired = 1000/this.targetFPS; - // Add some tolerance; frame lengths shorter than this are considered to be @ the desired frame length - this.frameLengthDesiredThreshold = 1000/(this.targetFPS - 2); - // During tier sampling get at least this slow to find the right complexity range - this.frameLengthTierThreshold = 1000/(this.targetFPS * 0.5); - // Try to make each ramp get this slow so that we can cross the break point - this.frameLengthRampLowerThreshold = 1000/(this.targetFPS * 0.75); - // Do not let the regression calculation at the maximum complexity of a ramp get slower than this threshold - this.frameLengthRampUpperThreshold = 1000/(this.targetFPS / 3); - }, { - - // If the engine can handle the tier's complexity at the desired frame rate, test for a short - // period, then move on to the next tier - tierFastTestLength: 250, - // If the engine is under stress, let the test run a little longer to let the measurement settle - tierSlowTestLength: 750, - // Tier intervals must have this number of non-outlier frames in order to end. - numberOfFramesRequiredInInterval: 9, - - rampWarmupLength: 200, - - start: function(startTimestamp, stage) - { - Controller.prototype.start.call(this, startTimestamp, stage); - this._rampStartTimestamp = 0; - this.intervalSamplingLength = 100; - this._frameTimeHistory = []; - }, - - registerFrameTime: function(lastFrameLength) - { - this._frameTimeHistory.push(lastFrameLength); - }, - - intervalHasConcluded: function(timestamp) - { - if (!Controller.prototype.intervalHasConcluded.call(this, timestamp)) - return false; - - return this._finishedTierSampling || this.filterOutOutliers(this._frameTimeHistory).length > this.numberOfFramesRequiredInInterval; - }, - - didFinishInterval: function(timestamp, stage, intervalAverageFrameLength) - { - this._frameTimeHistory = []; - if (!this._finishedTierSampling) { - if (this._tierStartTimestamp > 0 && timestamp < this._tierStartTimestamp + this.tierFastTestLength) - return; - - var currentComplexity = stage.complexity(); - var currentFrameLength = this._frameLengthEstimator.estimate; - if (currentFrameLength < this.frameLengthTierThreshold) { - var isAnimatingAtTargetFPS = currentFrameLength < this.frameLengthDesiredThreshold; - var hasFinishedSlowTierTest = timestamp > this._tierStartTimestamp + this.tierSlowTestLength; - - if (!isAnimatingAtTargetFPS && !hasFinishedSlowTierTest) - return; - - // We're measuring at the target fps, so quickly move on to the next tier, or - // we're slower than the target fps, but we've let this tier run long enough to - // get an estimate - this._lastTierComplexity = currentComplexity; - this._lastTierFrameLength = currentFrameLength; - - if (currentComplexity <= 50) - this._tier += 1/2; - else if (currentComplexity <= 10000) - this._tier += 1/4; - else - this._tier += 1/8; - this._endTimestamp = timestamp + this._testLength; - var nextTierComplexity = Math.max(Math.round(Math.pow(10, this._tier)), currentComplexity + 1); - stage.tune(nextTierComplexity - currentComplexity); - - // Some tests may be unable to go beyond a certain capacity. If so, don't keep moving up tiers - if (stage.complexity() - currentComplexity > 0 || nextTierComplexity == 1) { - this._tierStartTimestamp = timestamp; - this.mark("Complexity: " + nextTierComplexity, timestamp); - return; - } - } else if (timestamp < this._tierStartTimestamp + this.tierSlowTestLength) - return; - - this._finishedTierSampling = true; - this.isFrameLengthEstimatorEnabled = false; - this.intervalSamplingLength = 120; - - // Extend the test length so that the full test length is made of the ramps - this._endTimestamp = timestamp + this._testLength; - this.mark(Strings.json.samplingStartTimeOffset, timestamp); - - this._minimumComplexity = 1; - this._possibleMinimumComplexity = this._minimumComplexity; - this._minimumComplexityEstimator.sample(this._minimumComplexity); - - // Sometimes this last tier will drop the frame length well below the threshold. - // Avoid going down that far since it means fewer measurements are taken in the target fps area. - // Interpolate a maximum complexity that gets us around the lowest threshold. - // Avoid doing this calculation if we never get out of the first tier (where this._lastTierComplexity is undefined). - if (this._lastTierComplexity && this._lastTierComplexity != currentComplexity) - this._maximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthTierThreshold, this._lastTierFrameLength, currentFrameLength), this._lastTierComplexity, currentComplexity)); - else { - // If the browser is capable of handling the most complex version of the test, use that - this._maximumComplexity = currentComplexity; - } - this._possibleMaximumComplexity = this._maximumComplexity; - - // If we get ourselves onto a ramp where the maximum complexity does not yield slow enough FPS, - // We'll use this as a boundary to find a higher maximum complexity for the next ramp - this._lastTierComplexity = currentComplexity; - this._lastTierFrameLength = currentFrameLength; - - // First ramp - stage.tune(this._maximumComplexity - currentComplexity); - this._rampDidWarmup = false; - // Start timestamp represents start of ramp iteration and warm up - this._rampStartTimestamp = timestamp; - return; - } - - if ((timestamp - this._rampStartTimestamp) < this.rampWarmupLength) - return; - - if (this._rampDidWarmup) - return; - - this._rampDidWarmup = true; - this._currentRampLength = this._rampStartTimestamp + this._rampLength - timestamp; - // Start timestamp represents start of ramp down, after warm up - this._rampStartTimestamp = timestamp; - this._rampStartIndex = this._sampler.sampleCount; - }, - - tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength) - { - if (!this._rampDidWarmup) - return; - - this._intervalFrameLengthEstimator.sample(lastFrameLength); - if (!didFinishInterval) - return; - - var currentComplexity = stage.complexity(); - var intervalFrameLengthMean = this._intervalFrameLengthEstimator.mean(); - var intervalFrameLengthStandardDeviation = this._intervalFrameLengthEstimator.standardDeviation(); - - if (intervalFrameLengthMean < this.frameLengthDesiredThreshold && this._intervalFrameLengthEstimator.cdf(this.frameLengthDesiredThreshold) > .9) { - this._possibleMinimumComplexity = Math.max(this._possibleMinimumComplexity, currentComplexity); - } else if (intervalFrameLengthStandardDeviation > 2) { - // In the case where we might have found a previous interval where the target fps was reached. We hit a significant blip, - // so we should resample this area in the next ramp. - this._possibleMinimumComplexity = 1; - } - if (intervalFrameLengthMean - intervalFrameLengthStandardDeviation > this.frameLengthRampLowerThreshold) - this._possibleMaximumComplexity = Math.min(this._possibleMaximumComplexity, currentComplexity); - this._intervalFrameLengthEstimator.reset(); - - var progress = (timestamp - this._rampStartTimestamp) / this._currentRampLength; - - if (progress < 1) { - // Reframe progress percentage so that the last interval of the ramp can sample at minimum complexity - progress = (timestamp - this._rampStartTimestamp) / (this._currentRampLength - this.intervalSamplingLength); - stage.tune(Math.max(this._minimumComplexity, Math.floor(Utilities.lerp(progress, this._maximumComplexity, this._minimumComplexity))) - currentComplexity); - return; - } - - var regressionData = []; - for (var i = this._rampStartIndex; i < this._sampler.sampleCount; ++i) { - if (this._getFrameType(this._sampler.samples, i) == Strings.json.mutationFrameType) - continue; - regressionData.push([ this._getComplexity(this._sampler.samples, i), this._getFrameLength(this._sampler.samples, i) ]); - } - - var regression = new Regression(regressionData, this._sampler.sampleCount - 1, this._rampStartIndex, { desiredFrameLength: this.frameLengthDesired }); - this._rampRegressions.push(regression); - - var frameLengthAtMaxComplexity = regression.valueAt(this._maximumComplexity); - if (frameLengthAtMaxComplexity < this.frameLengthRampLowerThreshold) - this._possibleMaximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthRampLowerThreshold, frameLengthAtMaxComplexity, this._lastTierFrameLength), this._maximumComplexity, this._lastTierComplexity)); - // If the regression doesn't fit the first segment at all, keep the minimum bound at 1 - if ((timestamp - this._sampler.samples[sampleTimeIndex][this._sampler.sampleCount - regression.n1]) / this._currentRampLength < .25) - this._possibleMinimumComplexity = 1; - - this._minimumComplexityEstimator.sample(this._possibleMinimumComplexity); - this._minimumComplexity = Math.round(this._minimumComplexityEstimator.mean()); - - if (frameLengthAtMaxComplexity < this.frameLengthRampUpperThreshold) { - this._changePointEstimator.sample(regression.complexity); - // Ideally we'll target the change point in the middle of the ramp. If the range of the ramp is too small, there isn't enough - // range along the complexity (x) axis for a good regression calculation to be made, so force at least a range of 5 - // particles. Make it possible to increase the maximum complexity in case unexpected noise caps the regression too low. - this._maximumComplexity = Math.round(this._minimumComplexity + - Math.max(5, - this._possibleMaximumComplexity - this._minimumComplexity, - (this._changePointEstimator.mean() - this._minimumComplexity) * 2)); - } else { - // The slowest samples weighed the regression too heavily - this._maximumComplexity = Math.max(Math.round(.8 * this._maximumComplexity), this._minimumComplexity + 5); - } - - // Next ramp - stage.tune(this._maximumComplexity - stage.complexity()); - this._rampDidWarmup = false; - // Start timestamp represents start of ramp iteration and warm up - this._rampStartTimestamp = timestamp; - this._possibleMinimumComplexity = 1; - this._possibleMaximumComplexity = this._maximumComplexity; - }, - - processSamples: function(results) - { - results[Strings.json.marks] = this._processMarks(); - // Have samplingTimeOffset represent time 0 - var startTimestamp = this._marks[Strings.json.samplingStartTimeOffset].time; - for (var markName in results[Strings.json.marks]) { - results[Strings.json.marks][markName].time -= startTimestamp; - } - - results[Strings.json.samples] = {}; - - var controllerSamples = this._processControllerSamples(); - results[Strings.json.samples][Strings.json.controller] = controllerSamples; - controllerSamples.forEach(function(timeSample) { - controllerSamples.setFieldInDatum(timeSample, Strings.json.time, controllerSamples.getFieldInDatum(timeSample, Strings.json.time) - startTimestamp); - }); - - // Aggregate all of the ramps into one big complexity-frameLength dataset - var complexitySamples = new SampleData(controllerSamples.fieldMap); - results[Strings.json.samples][Strings.json.complexity] = complexitySamples; - - results[Strings.json.controller] = []; - this._rampRegressions.forEach(function(ramp) { - var startIndex = ramp.startIndex, endIndex = ramp.endIndex; - var startTime = controllerSamples.getFieldInDatum(startIndex, Strings.json.time); - var endTime = controllerSamples.getFieldInDatum(endIndex, Strings.json.time); - var startComplexity = controllerSamples.getFieldInDatum(startIndex, Strings.json.complexity); - var endComplexity = controllerSamples.getFieldInDatum(endIndex, Strings.json.complexity); - - var regression = {}; - results[Strings.json.controller].push(regression); - - var percentage = (ramp.complexity - startComplexity) / (endComplexity - startComplexity); - var inflectionTime = startTime + percentage * (endTime - startTime); - - regression[Strings.json.regressions.segment1] = [ - [startTime, ramp.s2 + ramp.t2 * startComplexity], - [inflectionTime, ramp.s2 + ramp.t2 * ramp.complexity] - ]; - regression[Strings.json.regressions.segment2] = [ - [inflectionTime, ramp.s1 + ramp.t1 * ramp.complexity], - [endTime, ramp.s1 + ramp.t1 * endComplexity] - ]; - regression[Strings.json.complexity] = ramp.complexity; - regression[Strings.json.regressions.startIndex] = startIndex; - regression[Strings.json.regressions.endIndex] = endIndex; - regression[Strings.json.regressions.profile] = ramp.profile; - - for (var j = startIndex; j <= endIndex; ++j) - complexitySamples.push(controllerSamples.at(j)); - }); - - this._processComplexitySamples(complexitySamples); - } -}); - -Stage = Utilities.createClass( - function() - { - }, { - - initialize: function(benchmark) - { - this._benchmark = benchmark; - this._element = document.getElementById("stage"); - this._element.setAttribute("width", document.body.offsetWidth); - this._element.setAttribute("height", document.body.offsetHeight); - this._size = Point.elementClientSize(this._element).subtract(Insets.elementPadding(this._element).size); - }, - - get element() - { - return this._element; - }, - - get size() - { - return this._size; - }, - - complexity: function() - { - return 0; - }, - - tune: function() - { - throw "Not implemented"; - }, - - animate: function() - { - throw "Not implemented"; - }, - - clear: function() - { - return this.tune(-this.tune(0)); - } -}); - -Utilities.extendObject(Stage, { - random: function(min, max) - { - return (Pseudo.random() * (max - min)) + min; - }, - - randomBool: function() - { - return !!Math.round(Pseudo.random()); - }, - - randomSign: function() - { - return Pseudo.random() >= .5 ? 1 : -1; - }, - - randomInt: function(min, max) - { - return Math.floor(this.random(min, max + 1)); - }, - - randomPosition: function(maxPosition) - { - return new Point(this.randomInt(0, maxPosition.x), this.randomInt(0, maxPosition.y)); - }, - - randomSquareSize: function(min, max) - { - var side = this.random(min, max); - return new Point(side, side); - }, - - randomVelocity: function(maxVelocity) - { - return this.random(maxVelocity / 8, maxVelocity); - }, - - randomAngle: function() - { - return this.random(0, Math.PI * 2); - }, - - randomColor: function() - { - var min = 32; - var max = 256 - 32; - return "#" - + this.randomInt(min, max).toString(16) - + this.randomInt(min, max).toString(16) - + this.randomInt(min, max).toString(16); - }, - - randomStyleMixBlendMode: function() - { - var mixBlendModeList = [ - 'normal', - 'multiply', - 'screen', - 'overlay', - 'darken', - 'lighten', - 'color-dodge', - 'color-burn', - 'hard-light', - 'soft-light', - 'difference', - 'exclusion', - 'hue', - 'saturation', - 'color', - 'luminosity' - ]; - - return mixBlendModeList[this.randomInt(0, mixBlendModeList.length)]; - }, - - randomStyleFilter: function() - { - var filterList = [ - 'grayscale(50%)', - 'sepia(50%)', - 'saturate(50%)', - 'hue-rotate(180)', - 'invert(50%)', - 'opacity(50%)', - 'brightness(50%)', - 'contrast(50%)', - 'blur(10px)', - 'drop-shadow(10px 10px 10px gray)' - ]; - - return filterList[this.randomInt(0, filterList.length)]; - }, - - randomElementInArray: function(array) - { - return array[Stage.randomInt(0, array.length - 1)]; - }, - - rotatingColor: function(cycleLengthMs, saturation, lightness) - { - return "hsl(" - + Stage.dateFractionalValue(cycleLengthMs) * 360 + ", " - + ((saturation || .8) * 100).toFixed(0) + "%, " - + ((lightness || .35) * 100).toFixed(0) + "%)"; - }, - - // Returns a fractional value that wraps around within [0,1] - dateFractionalValue: function(cycleLengthMs) - { - return (Date.now() / (cycleLengthMs || 2000)) % 1; - }, - - // Returns an increasing value slowed down by factor - dateCounterValue: function(factor) - { - return Date.now() / factor; - }, - - randomRotater: function() - { - return new Rotater(this.random(1000, 10000)); - } -}); - -Rotater = Utilities.createClass( - function(rotateInterval) - { - this._timeDelta = 0; - this._rotateInterval = rotateInterval; - this._isSampling = false; - }, { - - get interval() - { - return this._rotateInterval; - }, - - next: function(timeDelta) - { - this._timeDelta = (this._timeDelta + timeDelta) % this._rotateInterval; - }, - - degree: function() - { - return (360 * this._timeDelta) / this._rotateInterval; - }, - - rotateZ: function() - { - return "rotateZ(" + Math.floor(this.degree()) + "deg)"; - }, - - rotate: function(center) - { - return "rotate(" + Math.floor(this.degree()) + ", " + center.x + "," + center.y + ")"; - } -}); - -Benchmark = Utilities.createClass( - function(stage, options) - { - this._animateLoop = this._animateLoop.bind(this); - this._warmupLength = options["warmup-length"]; - this._frameCount = 0; - this._warmupFrameCount = options["warmup-frame-count"]; - this._firstFrameMinimumLength = options["first-frame-minimum-length"]; - - this._stage = stage; - this._stage.initialize(this, options); - - switch (options["time-measurement"]) - { - case "performance": - if (window.performance && window.performance.now) - this._getTimestamp = performance.now.bind(performance); - else - this._getTimestamp = null; - break; - case "raf": - this._getTimestamp = null; - break; - case "date": - this._getTimestamp = Date.now; - break; - } - - options["test-interval"] *= 1000; - switch (options["controller"]) - { - case "fixed": - this._controller = new FixedController(this, options); - break; - case "adaptive": - this._controller = new AdaptiveController(this, options); - break; - case "ramp": - this._controller = new RampController(this, options); - break; - } - }, { - - get stage() - { - return this._stage; - }, - - get timestamp() - { - return this._currentTimestamp - this._benchmarkStartTimestamp; - }, - - backgroundColor: function() - { - var stage = window.getComputedStyle(document.getElementById("stage")); - return stage["background-color"]; - }, - - run: function() - { - return this.waitUntilReady().then(function() { - this._finishPromise = new SimplePromise; - this._previousTimestamp = undefined; - this._didWarmUp = false; - this._stage.tune(this._controller.initialComplexity - this._stage.complexity()); - this._animateLoop(); - return this._finishPromise; - }.bind(this)); - }, - - // Subclasses should override this if they have setup to do prior to commencing. - waitUntilReady: function() - { - var promise = new SimplePromise; - promise.resolve(); - return promise; - }, - - _animateLoop: function(timestamp) - { - timestamp = (this._getTimestamp && this._getTimestamp()) || timestamp; - this._currentTimestamp = timestamp; - - if (this._controller.shouldStop(timestamp)) { - this._finishPromise.resolve(this._controller.results()); - return; - } - - if (!this._didWarmUp) { - if (!this._previousTimestamp) { - this._previousTimestamp = timestamp; - this._benchmarkStartTimestamp = timestamp; - } else if (timestamp - this._previousTimestamp >= this._warmupLength && this._frameCount >= this._warmupFrameCount) { - this._didWarmUp = true; - this._benchmarkStartTimestamp = timestamp; - this._controller.start(timestamp, this._stage); - this._previousTimestamp = timestamp; - - while (this._getTimestamp && this._getTimestamp() - timestamp < this._firstFrameMinimumLength) { - } - } - - this._stage.animate(0); - ++this._frameCount; - requestAnimationFrame(this._animateLoop); - return; - } - - this._controller.update(timestamp, this._stage); - this._stage.animate(timestamp - this._previousTimestamp); - this._previousTimestamp = timestamp; - requestAnimationFrame(this._animateLoop); - } -}); diff --git a/MotionMark/tests/resources/math.js b/MotionMark/tests/resources/math.js deleted file mode 100644 index e96a517..0000000 --- a/MotionMark/tests/resources/math.js +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -SimpleKalmanEstimator = Utilities.createSubclass(Experiment, - function(processError, measurementError) { - Experiment.call(this, false); - var error = .5 * (Math.sqrt(processError * processError + 4 * processError * measurementError) - processError); - this._gain = error / (error + measurementError); - }, { - - sample: function(newMeasurement) - { - if (!this._initialized) { - this._initialized = true; - this.estimate = newMeasurement; - return; - } - - this.estimate = this.estimate + this._gain * (newMeasurement - this.estimate); - }, - - reset: function() - { - Experiment.prototype.reset.call(this); - this._initialized = false; - this.estimate = 0; - } -}); - -PIDController = Utilities.createClass( - function(ysp) - { - this._ysp = ysp; - this._out = 0; - - this._Kp = 0; - this._stage = PIDController.stages.WARMING; - - this._eold = 0; - this._I = 0; - }, { - - // Determines whether the current y is - // before ysp => (below ysp if ysp > y0) || (above ysp if ysp < y0) - // after ysp => (above ysp if ysp > y0) || (below ysp if ysp < y0) - _yPosition: function(y) - { - return (y < this._ysp) == (this._y0 < this._ysp) - ? PIDController.yPositions.BEFORE_SETPOINT - : PIDController.yPositions.AFTER_SETPOINT; - }, - - // Calculate the ultimate distance from y0 after time t. We want to move very - // slowly at the beginning to see how adding few items to the test can affect - // its output. The complexity of a single item might be big enough to keep the - // proportional gain very small but achieves the desired progress. But if y does - // not change significantly after adding few items, that means we need a much - // bigger gain. So we need to move over a cubic curve which increases very - // slowly with small t values but moves very fast with larger t values. - // The basic formula is: y = t^3 - // Change the formula to reach y=1 after 1000 ms: y = (t/1000)^3 - // Change the formula to reach y=(ysp - y0) after 1000 ms: y = (ysp - y0) * (t/1000)^3 - _distanceUltimate: function(t) - { - return (this._ysp - this._y0) * Math.pow(t / 1000, 3); - }, - - // Calculates the distance of y relative to y0. It also ensures we do not return - // zero by returning a epsilon value in the same direction as ultimate distance. - _distance: function(y, du) - { - const epsilon = 0.0001; - var d = y - this._y0; - return du < 0 ? Math.min(d, -epsilon) : Math.max(d, epsilon); - }, - - // Decides how much the proportional gain should be increased during the manual - // gain stage. We choose to use the ratio of the ultimate distance to the current - // distance as an indication of how much the system is responsive. We want - // to keep the increment under control so it does not cause the system instability - // So we choose to take the natural logarithm of this ratio. - _gainIncrement: function(t, y, e) - { - var du = this._distanceUltimate(t); - var d = this._distance(y, du); - return Math.log(du / d) * 0.1; - }, - - // Update the stage of the controller based on its current stage and the system output - _updateStage: function(y) - { - var yPosition = this._yPosition(y); - - switch (this._stage) { - case PIDController.stages.WARMING: - if (yPosition == PIDController.yPositions.AFTER_SETPOINT) - this._stage = PIDController.stages.OVERSHOOT; - break; - - case PIDController.stages.OVERSHOOT: - if (yPosition == PIDController.yPositions.BEFORE_SETPOINT) - this._stage = PIDController.stages.UNDERSHOOT; - break; - - case PIDController.stages.UNDERSHOOT: - if (yPosition == PIDController.yPositions.AFTER_SETPOINT) - this._stage = PIDController.stages.SATURATE; - break; - } - }, - - // Manual tuning is used before calculating the PID controller gains. - _tuneP: function(e) - { - // The output is the proportional term only. - return this._Kp * e; - }, - - // PID tuning function. Kp, Ti and Td were already calculated - _tunePID: function(h, y, e) - { - // Proportional term. - var P = this._Kp * e; - - // Integral term is the area under the curve starting from the beginning - // till the current time. - this._I += (this._Kp / this._Ti) * ((e + this._eold) / 2) * h; - - // Derivative term is the slope of the curve at the current time. - var D = (this._Kp * this._Td) * (e - this._eold) / h; - - // The ouput is a PID function. - return P + this._I + D; - }, - - // Apply different strategies for the tuning based on the stage of the controller. - _tune: function(t, h, y, e) - { - switch (this._stage) { - case PIDController.stages.WARMING: - // This is the first stage of the Zieglerâ€Nichols method. It increments - // the proportional gain till the system output passes the set-point value. - if (typeof this._y0 == "undefined") { - // This is the first time a tuning value is required. We want the test - // to add only one item. So we need to return -1 which forces us to - // choose the initial value of Kp to be = -1 / e - this._y0 = y; - this._Kp = -1 / e; - } else { - // Keep incrementing the Kp as long as we have not reached the - // set-point yet - this._Kp += this._gainIncrement(t, y, e); - } - - return this._tuneP(e); - - case PIDController.stages.OVERSHOOT: - // This is the second stage of the Zieglerâ€Nichols method. It measures the - // oscillation period. - if (typeof this._t0 == "undefined") { - // t is the time of the begining of the first overshot - this._t0 = t; - this._Kp /= 2; - } - - return this._tuneP(e); - - case PIDController.stages.UNDERSHOOT: - // This is the end of the Zieglerâ€Nichols method. We need to calculate the - // integral and derivative periods. - if (typeof this._Ti == "undefined") { - // t is the time of the end of the first overshot - var Tu = t - this._t0; - - // Calculate the system parameters from Kp and Tu assuming - // a "some overshoot" control type. See: - // https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method - this._Ti = Tu / 2; - this._Td = Tu / 3; - this._Kp = 0.33 * this._Kp; - - // Calculate the tracking time. - this._Tt = Math.sqrt(this._Ti * this._Td); - } - - return this._tunePID(h, y, e); - - case PIDController.stages.SATURATE: - return this._tunePID(h, y, e); - } - - return 0; - }, - - // Ensures the system does not fluctuates. - _saturate: function(v, e) - { - var u = v; - - switch (this._stage) { - case PIDController.stages.OVERSHOOT: - case PIDController.stages.UNDERSHOOT: - // Calculate the min-max values of the saturation actuator. - if (typeof this._min == "undefined") - this._min = this._max = this._out; - else { - this._min = Math.min(this._min, this._out); - this._max = Math.max(this._max, this._out); - } - break; - - case PIDController.stages.SATURATE: - const limitPercentage = 0.90; - var min = this._min > 0 ? Math.min(this._min, this._max * limitPercentage) : this._min; - var max = this._max < 0 ? Math.max(this._max, this._min * limitPercentage) : this._max; - var out = this._out + u; - - // Clip the controller output to the min-max values - out = Math.max(Math.min(max, out), min); - u = out - this._out; - - // Apply the back-calculation and tracking - if (u != v) - u += (this._Kp * this._Tt / this._Ti) * e; - break; - } - - this._out += u; - return u; - }, - - // Called from the benchmark to tune its test. It uses Ziegler-Nichols method - // to calculate the controller parameters. It then returns a PID tuning value. - tune: function(t, h, y) - { - this._updateStage(y); - - // Current error. - var e = this._ysp - y; - var v = this._tune(t, h, y, e); - - // Save e for the next call. - this._eold = e; - - // Apply back-calculation and tracking to avoid integrator windup - return this._saturate(v, e); - } -}); - -Utilities.extendObject(PIDController, { - // This enum will be used to tell whether the system output (or the controller input) - // is moving towards the set-point or away from it. - yPositions: { - BEFORE_SETPOINT: 0, - AFTER_SETPOINT: 1 - }, - - // The Ziegler-Nichols method for is used tuning the PID controller. The workflow of - // the tuning is split into four stages. The first two stages determine the values - // of the PID controller gains. During these two stages we return the proportional - // term only. The third stage is used to determine the min-max values of the - // saturation actuator. In the last stage back-calculation and tracking are applied - // to avoid integrator windup. During the last two stages, we return a PID control - // value. - stages: { - WARMING: 0, // Increase the value of the Kp until the system output reaches ysp. - OVERSHOOT: 1, // Measure the oscillation period and the overshoot value - UNDERSHOOT: 2, // Return PID value and measure the undershoot value - SATURATE: 3 // Return PID value and apply back-calculation and tracking. - } -}); diff --git a/MotionMark/tests/resources/star.svg b/MotionMark/tests/resources/star.svg deleted file mode 100644 index 3c46ae0..0000000 --- a/MotionMark/tests/resources/star.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/MotionMark/tests/resources/yin-yang.png b/MotionMark/tests/resources/yin-yang.png deleted file mode 100644 index 3162f6e..0000000 Binary files a/MotionMark/tests/resources/yin-yang.png and /dev/null differ diff --git a/MotionMark/tests/resources/yin-yang.svg b/MotionMark/tests/resources/yin-yang.svg deleted file mode 100644 index 4412626..0000000 --- a/MotionMark/tests/resources/yin-yang.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/simple/resources/simple-canvas-paths.js b/MotionMark/tests/simple/resources/simple-canvas-paths.js deleted file mode 100644 index 143630d..0000000 --- a/MotionMark/tests/simple/resources/simple-canvas-paths.js +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -// === PAINT OBJECTS === - -CanvasLineSegment = Utilities.createClass( - function(stage) { - var radius = Stage.randomInt(10, 100); - var center = Stage.randomPosition(stage.size); - var delta = Point.pointOnCircle(Stage.randomAngle(), radius/2); - - this._point1 = center.add(delta); - this._point2 = center.subtract(delta); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 100); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.moveTo(this._point1.x, this._point1.y); - context.lineTo(this._point2.x, this._point2.y); - context.stroke(); - } -}); - -CanvasLinePoint = Utilities.createClass( - function(stage, coordinateMaximumFactor) { - var pointMaximum = new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y)); - this._point = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - }, { - - draw: function(context) { - context.lineTo(this._point.x, this._point.y); - } -}) - -CanvasQuadraticSegment = Utilities.createClass( - function(stage) { - var maxSize = Stage.randomInt(20, 200); - var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); - - this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 50); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.moveTo(this._point1.x, this._point1.y); - context.quadraticCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y); - context.stroke(); - } -}); - -CanvasQuadraticPoint = Utilities.createClass( - function(stage, coordinateMaximumFactor) { - var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y))); - this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - }, { - - draw: function(context) { - context.quadraticCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y); - } -}); - -CanvasBezierSegment = Utilities.createClass( - function(stage) { - var maxSize = Stage.randomInt(20, 200); - var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); - - this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point4 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 50); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.moveTo(this._point1.x, this._point1.y); - context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._point4.x, this._point4.y); - context.stroke(); - } -}); - -CanvasBezierPoint = Utilities.createClass( - function(stage, coordinateMaximumFactor) { - var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y))); - this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - this._point3 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2)); - }, { - - draw: function(context) { - context.bezierCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y, this._point3.x, this._point3.y); - } -}); - -CanvasArcToSegment = Utilities.createClass( - function(stage) { - var maxSize = Stage.randomInt(20, 200); - var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); - - this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._radius = Stage.randomInt(20, 200); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 50); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.moveTo(this._point1.x, this._point1.y); - context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius); - context.stroke(); - } -}); - -CanvasArcToSegmentFill = Utilities.createClass( - function(stage) { - CanvasArcToSegment.call(this, stage); - }, { - - draw: function(context) { - context.fillStyle = this._color; - context.beginPath(); - context.moveTo(this._point1.x, this._point1.y); - context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius); - context.fill(); - } -}); - -CanvasArcSegment = Utilities.createClass( - function(stage) { - var maxSize = Stage.randomInt(20, 200); - var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); - - this._point = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); - this._radius = Stage.randomInt(20, 200); - this._startAngle = Stage.randomAngle(); - this._endAngle = Stage.randomAngle(); - this._counterclockwise = Stage.randomBool(); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 50); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); - context.stroke(); - } -}); - -CanvasArcSegmentFill = Utilities.createClass( - function(stage) { - CanvasArcSegment.call(this, stage); - }, { - - draw: function(context) { - context.fillStyle = this._color; - context.beginPath(); - context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); - context.fill(); - } -}); - -CanvasRect = Utilities.createClass( - function(stage) { - this._width = Stage.randomInt(20, 200); - this._height = Stage.randomInt(20, 200); - this._point = Stage.randomPosition(stage.size).subtract(new Point(this._width/2, this._height/2)); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 20); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.rect(this._point.x, this._point.y, this._width, this._height); - context.stroke(); - } -}); - -CanvasRectFill = Utilities.createClass( - function(stage) { - CanvasRect.call(this, stage); - }, { - - draw: function(context) { - context.fillStyle = this._color; - context.beginPath(); - context.rect(this._point.x, this._point.y, this._width, this._height); - context.fill(); - } -}); - -CanvasEllipse = Utilities.createClass( - function(stage) { - this._radius = new Point(Stage.randomInt(20, 200), Stage.randomInt(20, 200)); - var toCenter = Stage.randomPosition(stage.size).subtract(this._radius.multiply(.5)); - - this._center = Stage.randomPosition(this._radius).add(toCenter); - this._rotation = Stage.randomAngle(); - this._startAngle = Stage.randomAngle(); - this._endAngle = Stage.randomAngle(); - this._anticlockwise = Stage.randomBool(); - this._color = Stage.randomColor(); - this._lineWidth = Stage.randomInt(1, 20); - }, { - - draw: function(context) { - context.strokeStyle = this._color; - context.lineWidth = this._lineWidth; - context.beginPath(); - context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise); - context.stroke(); - } -}); - -CanvasEllipseFill = Utilities.createClass( - function(stage) { - CanvasEllipse.call(this, stage); - }, { - - draw: function(context) { - context.fillStyle = this._color; - context.beginPath(); - context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise); - context.fill(); - } -}); - -CanvasStroke = Utilities.createClass( - function (stage) { - this._object = new (Stage.randomElementInArray(this.objectTypes))(stage); - }, { - - objectTypes: [ - CanvasQuadraticSegment, - CanvasBezierSegment, - CanvasArcToSegment, - CanvasArcSegment, - CanvasRect, - CanvasEllipse - ], - - draw: function(context) { - this._object.draw(context); - } -}); - -CanvasFill = Utilities.createClass( - function (stage) { - this._object = new (Stage.randomElementInArray(this.objectTypes))(stage); - }, { - - objectTypes: [ - CanvasArcToSegmentFill, - CanvasArcSegmentFill, - CanvasRectFill, - CanvasEllipseFill - ], - - draw: function(context) { - this._object.draw(context); - } -}); - -// === STAGES === - -SimpleCanvasPathStrokeStage = Utilities.createSubclass(SimpleCanvasStage, - function(canvasObject) { - SimpleCanvasStage.call(this, canvasObject); - }, { - - animate: function() - { - var context = this.context; - context.clearRect(0, 0, this.size.x, this.size.y); - context.lineWidth = Stage.randomInt(1, 20); - context.strokeStyle = Stage.rotatingColor(); - context.beginPath(); - context.moveTo(this.size.x / 2, this.size.y / 2); - for (var i = 0, length = this.offsetIndex; i < length; ++i) - this.objects[i].draw(context); - context.stroke(); - } -}); - -SimpleCanvasPathFillStage = Utilities.createSubclass(SimpleCanvasStage, - function(canvasObject) { - SimpleCanvasStage.call(this, canvasObject); - }, { - - animate: function() - { - var context = this.context; - context.clearRect(0, 0, this.size.x, this.size.y); - context.fillStyle = Stage.rotatingColor(); - context.beginPath(); - context.moveTo(this.size.x / 2, this.size.y / 2); - for (var i = 0, length = this.offsetIndex; i < length; ++i) - this.objects[i].draw(context); - context.fill(); - } -}); - -CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage, - function() - { - SimpleCanvasStage.call(this, CanvasLineSegment); - }, { - - initialize: function(benchmark, options) - { - SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); - this.context.lineCap = options["lineCap"] || "butt"; - } -}); - -CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasPathStrokeStage, - function() - { - SimpleCanvasPathStrokeStage.call(this, CanvasLinePoint); - }, { - - initialize: function(benchmark, options) - { - SimpleCanvasPathStrokeStage.prototype.initialize.call(this, benchmark, options); - this.context.lineJoin = options["lineJoin"] || "bevel"; - } -}); - -CanvasLineDashStage = Utilities.createSubclass(SimpleCanvasStage, - function() - { - SimpleCanvasStage.call(this, CanvasLinePoint); - this._step = 0; - }, { - - initialize: function(benchmark, options) - { - SimpleCanvasStage.prototype.initialize.call(this, benchmark, options); - this.context.setLineDash([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - this.context.lineWidth = 1; - this.context.strokeStyle = "#000"; - }, - - animate: function() - { - var context = this.context; - context.clearRect(0, 0, this.size.x, this.size.y); - context.lineDashOffset = this._step++; - context.beginPath(); - context.moveTo(this.size.x / 2, this.size.y / 2); - for (var i = 0, length = this.offsetIndex; i < length; ++i) - this.objects[i].draw(context); - context.stroke(); - } -}); - -// === BENCHMARK === - -CanvasPathBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - var stage; - switch (options["pathType"]) { - case "line": - stage = new CanvasLineSegmentStage(); - break; - case "linePath": { - if ("lineJoin" in options) - stage = new CanvasLinePathStage(); - if ("lineDash" in options) - stage = new CanvasLineDashStage(); - break; - } - case "quadratic": - stage = new SimpleCanvasStage(CanvasQuadraticSegment); - break; - case "quadraticPath": - stage = new SimpleCanvasPathStrokeStage(CanvasQuadraticPoint); - break; - case "bezier": - stage = new SimpleCanvasStage(CanvasBezierSegment); - break; - case "bezierPath": - stage = new SimpleCanvasPathStrokeStage(CanvasBezierPoint); - break; - case "arcTo": - stage = new SimpleCanvasStage(CanvasArcToSegment); - break; - case "arc": - stage = new SimpleCanvasStage(CanvasArcSegment); - break; - case "rect": - stage = new SimpleCanvasStage(CanvasRect); - break; - case "ellipse": - stage = new SimpleCanvasStage(CanvasEllipse); - break; - case "lineFill": - stage = new SimpleCanvasPathFillStage(CanvasLinePoint); - break; - case "quadraticFill": - stage = new SimpleCanvasPathFillStage(CanvasQuadraticPoint); - break; - case "bezierFill": - stage = new SimpleCanvasPathFillStage(CanvasBezierPoint); - break; - case "arcToFill": - stage = new SimpleCanvasStage(CanvasArcToSegmentFill); - break; - case "arcFill": - stage = new SimpleCanvasStage(CanvasArcSegmentFill); - break; - case "rectFill": - stage = new SimpleCanvasStage(CanvasRectFill); - break; - case "ellipseFill": - stage = new SimpleCanvasStage(CanvasEllipseFill); - break; - case "strokes": - stage = new SimpleCanvasStage(CanvasStroke); - break; - case "fills": - stage = new SimpleCanvasStage(CanvasFill); - break; - } - - Benchmark.call(this, stage, options); - } -); - -window.benchmarkClass = CanvasPathBenchmark; - -})(); \ No newline at end of file diff --git a/MotionMark/tests/simple/resources/tiled-canvas-image.js b/MotionMark/tests/simple/resources/tiled-canvas-image.js deleted file mode 100644 index 3f0700c..0000000 --- a/MotionMark/tests/simple/resources/tiled-canvas-image.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -CanvasImageTile = Utilities.createClass( - function(stage, source) - { - this._context = stage.context; - this._size = stage.tileSize; - this.source = source; - }, { - - getImageData: function() - { - this._imagedata = this._context.getImageData(this.source.x, this.source.y, this._size.width, this._size.height); - }, - - putImageData: function(destination) - { - this._context.putImageData(this._imagedata, destination.x, destination.y); - } -}); - -TiledCanvasImageStage = Utilities.createSubclass(Stage, - function(element, options) - { - Stage.call(this); - }, { - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - this.context = this.element.getContext("2d"); - this._setupTiles(); - }, - - _setupTiles: function() - { - const maxTilesPerRow = 50; - const maxTilesPerCol = 50; - - this.tileSize = this.size.multiply(new Point(1 / maxTilesPerRow, 1 / maxTilesPerCol)); - - this._tiles = new Array(maxTilesPerRow * maxTilesPerCol); - - var source = Point.zero; - for (var index = 0; index < this._tiles.length; ++index) { - this._tiles[index] = new CanvasImageTile(this, source); - source = this._nextTilePosition(source); - } - - this._ctiles = 0; - }, - - _nextTilePosition: function(destination) - { - var next = destination.add(this.tileSize); - - if (next.x >= this._size.width) - return new Point(0, next.y >= this._size.height ? 0 : next.y); - - return new Point(next.x, destination.y); - }, - - tune: function(count) - { - this._ctiles += count; - - this._ctiles = Math.max(this._ctiles, 0); - this._ctiles = Math.min(this._ctiles, this._tiles.length); - }, - - _drawBackground: function() - { - var size = this._benchmark._stage.size; - var gradient = this.context.createLinearGradient(0, 0, size.width, 0); - gradient.addColorStop(0, "red"); - gradient.addColorStop(1, "white"); - this.context.save(); - this.context.fillStyle = gradient; - this.context.fillRect(0, 0, size.width, size.height); - this.context.restore(); - }, - - animate: function(timeDelta) - { - this._drawBackground(); - - if (!this._ctiles) - return; - - this._tiles.shuffle(); - - var destinations = new Array(this._ctiles); - for (var index = 0; index < this._ctiles; ++index) { - this._tiles[index].getImageData(); - destinations[index] = this._tiles[index].source; - } - - destinations.shuffle(); - - for (var index = 0; index < this._ctiles; ++index) - this._tiles[index].putImageData(destinations[index]); - }, - - complexity: function() - { - return this._ctiles; - } -}); - -TiledCanvasImageBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new TiledCanvasImageStage(), options); - } -); - -window.benchmarkClass = TiledCanvasImageBenchmark; - -})(); diff --git a/MotionMark/tests/simple/simple-canvas-paths.html b/MotionMark/tests/simple/simple-canvas-paths.html deleted file mode 100644 index a914548..0000000 --- a/MotionMark/tests/simple/simple-canvas-paths.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/simple/tiled-canvas-image.html b/MotionMark/tests/simple/tiled-canvas-image.html deleted file mode 100644 index 237aeac..0000000 --- a/MotionMark/tests/simple/tiled-canvas-image.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/svg/suits.html b/MotionMark/tests/svg/suits.html deleted file mode 100644 index a39d1d8..0000000 --- a/MotionMark/tests/svg/suits.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/svg/suits.js b/MotionMark/tests/svg/suits.js deleted file mode 100644 index 9916755..0000000 --- a/MotionMark/tests/svg/suits.js +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2018 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -(function() { - -var SuperSuitsParticle = window.SuitsParticle; -ClipSuit = Utilities.createSubclass(SuperSuitsParticle, - function(stage) - { - this.initialize(stage); - }, { - - isClipPath: true, - hasGradient: false, - move: function() - { - this.element.setAttribute("transform", "translate(" + (this.position.x - this.size.center.x) + "," + (this.position.y - this.size.center.x) + ")"); - } -}); - -ShapeSuit = Utilities.createSubclass(SuperSuitsParticle, - function(stage) - { - this.initialize(stage); - }, { - - isClipPath: false, - hasGradient: false, - move: function() - { - this.element.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.transformSuffix); - } -}); - -RotationSuit = Utilities.createSubclass(SuperSuitsParticle, - function(stage) - { - this.isClipPath = stage.particleCounter % 2; - this.initialize(stage); - }, { - - hasGradient: false, -}); - -GradientSuit = Utilities.createSubclass(SuperSuitsParticle, - function(stage) - { - this.isClipPath = stage.particleCounter % 2; - this.initialize(stage); - }, { - - hasGradient: true, - move: function() - { - this.element.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.transformSuffix); - } -}); - -StaticSuit = Utilities.createSubclass(SuperSuitsParticle, - function(stage) - { - this.isClipPath = stage.particleCounter % 2; - this.initialize(stage); - }, { - - hasGradient: true, - reset: function() - { - SuperSuitsParticle.prototype.reset.call(this); - this.originalPosition = Stage.randomPosition(this.stage.size); - this.transformSuffix = " rotate(" + Math.floor(Stage.randomAngle() * 180 / Math.PI) + ",0,0)" + this.transformSuffix; - }, - - move: function() - { - this.element.setAttribute("transform", "translate(" + this.originalPosition.x + "," + this.originalPosition.y + ") " + this.transformSuffix); - } -}); - -var SuitsBenchmark = window.benchmarkClass; -var SuitsDerivedBenchmark = Utilities.createSubclass(SuitsBenchmark, - function(options) - { - switch (options["style"]) { - case "clip": - window.SuitsParticle = ClipSuit; - break; - case "shape": - window.SuitsParticle = ShapeSuit; - break; - case "rotation": - window.SuitsParticle = RotationSuit; - break; - case "gradient": - window.SuitsParticle = GradientSuit; - break; - case "static": - window.SuitsParticle = StaticSuit; - break; - } - SuitsBenchmark.call(this, options); - } -); - -window.benchmarkClass = SuitsDerivedBenchmark; - -})(); diff --git a/MotionMark/tests/template/resources/template-canvas.js b/MotionMark/tests/template/resources/template-canvas.js deleted file mode 100644 index 9a0c727..0000000 --- a/MotionMark/tests/template/resources/template-canvas.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2015-2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -function TemplateCanvasObject(stage) -{ - // For the canvas stage, most likely you will need to create your - // animated object since it's only draw time thing. - - // Fill in your object data. -} - -TemplateCanvasObject.prototype = { - _draw: function() - { - // Draw your object. - }, - - animate: function(timeDelta) - { - // Redraw the animated object. The last time this animated - // item was drawn before 'timeDelta'. - - // Move your object. - - // Redraw your object. - this._draw(); - } -}; - -TemplateCanvasStage = Utilities.createSubclass(Stage, - function() - { - Stage.call(this); - }, { - - initialize: function(benchmark, options) - { - Stage.prototype.initialize.call(this, benchmark, options); - this.context = this.element.getContext("2d"); - - // Define a collection for your objects. - }, - - tune: function(count) - { - // If count is -ve, -count elements need to be removed form the - // stage. If count is +ve, +count elements need to be added to - // the stage. - - // Change objects in the stage. - }, - - animate: function(timeDelta) - { - // Animate the elements such that all of them are redrawn. Most - // likely you will need to call TemplateCanvasObject.animate() - // for all your animated objects here. - - // Most likely you will need to clear the canvas with every redraw. - this.context.clearRect(0, 0, this.size.x, this.size.y); - - // Loop through all your objects and ask them to animate. - } -}); - -TemplateCanvasBenchmark = Utilities.createSubclass(Benchmark, - function(options) - { - Benchmark.call(this, new TemplateCanvasStage(), options); - }, { - - // Override this function if the benchmark needs to wait for resources to be - // loaded. - // - // Default implementation returns a resolved promise, so that the benchmark - // benchmark starts right away. Here's an example where we're waiting 5 - // seconds before starting the benchmark. - waitUntilReady: function() - { - var promise = new SimplePromise; - window.setTimeout(function() { - promise.resolve(); - }, 5000); - return promise; - } -}); - -window.benchmarkClass = TemplateCanvasBenchmark; - -})(); \ No newline at end of file diff --git a/MotionMark/tests/template/template-canvas.html b/MotionMark/tests/template/template-canvas.html deleted file mode 100644 index bdcab6f..0000000 --- a/MotionMark/tests/template/template-canvas.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/template/template-css.html b/MotionMark/tests/template/template-css.html deleted file mode 100644 index ed6b6ca..0000000 --- a/MotionMark/tests/template/template-css.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - -
- - - - - - - - diff --git a/MotionMark/tests/template/template-svg.html b/MotionMark/tests/template/template-svg.html deleted file mode 100644 index eb7a034..0000000 --- a/MotionMark/tests/template/template-svg.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/MotionMark/tests/text/design-6.html b/MotionMark/tests/text/design-6.html deleted file mode 100644 index decbdd2..0000000 --- a/MotionMark/tests/text/design-6.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - - - - - - diff --git a/MotionMark/tests/text/design-6.js b/MotionMark/tests/text/design-6.js deleted file mode 100644 index 9401657..0000000 --- a/MotionMark/tests/text/design-6.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -// The MotionMark-based TextBenchmark should already be set to |window.benchmarkClass| -var TextBenchmark = window.benchmarkClass; -var TextTemplateBenchmark = Utilities.createSubclass(TextBenchmark, - function(options) - { - var dataset; - switch (options["corpus"]) { - case "latin": - dataset = [ - "σχέδιο", - "umění", - "design", - "искусство", - "conception", - "diseño" - ]; - break; - case "cjk": - dataset = [ - "设计", - "디자인", - "デザイン", - "예술", - "使吃惊", - "がいねん", - ]; - break; - case "arabic": - dataset = [ - {text: "تصميم", direction: "rtl"}, - "வடிவமைப்பு", - "योजना", - {text: "לְעַצֵב", direction: "rtl"}, - {text: "خلاق", direction: "rtl"}, - "ศิลปะ", - ]; - break; - } - - dataset.forEach(function(entry, i) { - var td = document.getElementById("cell" + i); - if (typeof entry === 'string') { - td.innerText = entry; - } else { - td.innerText = entry.text; - td.classList.add("rtl"); - } - }) - - TextBenchmark.call(this, options); - } -); - -window.benchmarkClass = TextTemplateBenchmark; - -})(); \ No newline at end of file diff --git a/MotionMark/tests/text/design.html b/MotionMark/tests/text/design.html deleted file mode 100644 index 2de4977..0000000 --- a/MotionMark/tests/text/design.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - - - - - - diff --git a/MotionMark/tests/text/design.js b/MotionMark/tests/text/design.js deleted file mode 100644 index 9ec8a80..0000000 --- a/MotionMark/tests/text/design.js +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - -// The MotionMark-based TextBenchmark should already be set to |window.benchmarkClass| -var TextBenchmark = window.benchmarkClass; -var TextTemplateBenchmark = Utilities.createSubclass(TextBenchmark, - function(options) - { - var dataset; - switch (options["corpus"]) { - case "latin": - dataset = [ - "σχέδιο", - "umění", - "suunnittelu", - "design", - "deseń", - "искусство", - "дизайн", - "conception", - "kunst", - "konstruktion", - "τέχνη", - "diseño" - ]; - break; - case "cjk": - dataset = [ - "设计", - "디자인", - "デザイン", - "がいねん", - "藝術", - "养殖", - "예술", - "展開する", - "발달", - "技術", - "驚き", - "使吃惊", - ]; - break; - case "arabic": - dataset = [ - {text: "تصميم", direction: "rtl"}, - "வடிவமைப்பு", - "योजना", - {text: "לְעַצֵב", direction: "rtl"}, - {text: "خلاق", direction: "rtl"}, - "ศิลปะ", - "कौशल", - {text: "אָמָנוּת", direction: "rtl"}, - "கலை", - "ดีไซน์", - "পরিকল্পনা", - {text: "ډیزاین", direction: "rtl"}, - ]; - break; - } - - dataset.forEach(function(entry, i) { - var td = document.getElementById("cell" + i); - if (typeof entry === 'string') { - td.innerText = entry; - } else { - td.innerText = entry.text; - td.classList.add("rtl"); - } - }) - - TextBenchmark.call(this, options); - } -); - -window.benchmarkClass = TextTemplateBenchmark; - -})(); \ No newline at end of file diff --git a/MotionMark/unit-tests/resources/js-test.js b/MotionMark/unit-tests/resources/js-test.js new file mode 100644 index 0000000..2becb06 --- /dev/null +++ b/MotionMark/unit-tests/resources/js-test.js @@ -0,0 +1,968 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Copyright 2023 Apple Inc. All rights reserved. + +if (self.testRunner) { + // svg/dynamic-updates tests set enablePixelTesting=true, as we want to dump text + pixel results + if (self.enablePixelTesting) + testRunner.dumpAsTextWithPixelResults(); + else + testRunner.dumpAsText(); +} + +var description, debug, didFailSomeTests, successfullyParsed; + +didFailSomeTests = false; + +var expectingError; // set by shouldHaveError() +var expectedErrorMessage; // set by onerror when expectingError is true +var unexpectedErrorMessage; // set by onerror when expectingError is not true + +(function() { + + function createHTMLElement(tagName) + { + // FIXME: In an XML document, document.createElement() creates an element with a null namespace URI. + // So, we need use document.createElementNS() to explicitly create an element with the specified + // tag name in the HTML namespace. We can remove this function and use document.createElement() + // directly once we fix . + if (document.createElementNS) + return document.createElementNS("http://www.w3.org/1999/xhtml", tagName); + return document.createElement(tagName); + } + + var rootElement = null; + function ensureRootElement() + { + if (!rootElement || !rootElement.isConnected) { + rootElement = document.body || document.documentElement; + if (document.documentElement.namespaceURI == 'http://www.w3.org/2000/svg') { + // FIXME: Make the test harness use SVG elements naively. + var foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'); + foreignObject.setAttribute('x', '0px'); + foreignObject.setAttribute('y', '0px'); + foreignObject.setAttribute('width', '100%'); + foreignObject.setAttribute('height', '100%'); + foreignObject.setAttribute('style', 'padding: 10px; background-color: rgba(255, 255, 255, 0.5)'); + document.documentElement.appendChild(foreignObject); + rootElement = foreignObject; + } + } + return rootElement; + } + + moveForeignObjectToTopIfNeeded = function () { + if (rootElement && rootElement.localName == 'foreignObject') + document.documentElement.appendChild(rootElement); + } + + getOrCreate = function getOrCreate(id, tagName) + { + var element = document.getElementById(id); + if (element) + return element; + + element = createHTMLElement(tagName); + element.id = id; + var refNode; + var parent = ensureRootElement(); + + if (id == "description") + refNode = getOrCreate("console", "div"); + else + refNode = parent.firstChild; + + parent.insertBefore(element, refNode); + return element; + } + + description = function description(msg, quiet) + { + // For MSIE 6 compatibility + var span = createHTMLElement("span"); + if (quiet) + span.innerHTML = '

' + msg + '

On success, you will see no "FAIL" messages, followed by "TEST COMPLETE".

'; + else + span.innerHTML = '

' + msg + '

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

'; + + var description = getOrCreate("description", "p"); + if (description.firstChild) + description.replaceChild(span, description.firstChild); + else + description.appendChild(span); + }; + + debug = function debug(msg) + { + var span = createHTMLElement("span"); + span.innerHTML = msg + '
'; + getOrCreate("console", "div").appendChild(span); + }; + + var css = + ".pass {" + + "font-weight: bold;" + + "color: green;" + + "}" + + ".fail {" + + "font-weight: bold;" + + "color: red;" + + "}" + + "#console {" + + "white-space: pre-wrap;" + + "font-family: monospace;" + + "}"; + + function insertStyleSheet() + { + var styleElement = createHTMLElement("style"); + styleElement.textContent = css; + (document.head || ensureRootElement()).appendChild(styleElement); + } + + function handleTestFinished() + { + // FIXME: Get rid of this boolean. + wasPostTestScriptParsed = true; + if (window.jsTestIsAsync) { + if (window.testRunner) + testRunner.waitUntilDone(); + if (window.wasFinishJSTestCalled) + finishJSTest(); + } else + finishJSTest(); + } + + if (!isWorker()) { + window.addEventListener('DOMContentLoaded', function() { + // Call waitUntilDone() as early as possible otherwise some tests may complete before + // the load event has fired. + if (window.jsTestIsAsync && window.testRunner) + testRunner.waitUntilDone(); + + // Some tests set jsTestIsAsync in load event handler. Adding the listener late + // makes handleTestFinished() run after the test handles load events. + window.addEventListener("load", handleTestFinished, false); + }, false); + insertStyleSheet(); + } + + if (!self.isOnErrorTest) { + self.onerror = function(message) + { + if (self.expectingError) { + self.expectedErrorMessage = message; + self.expectingError = false; + return; + } + self.unexpectedErrorMessage = message; + if (self.jsTestIsAsync) { + self.testFailed("Unexpected error: " + message); + finishJSTest(); + } + }; + } +})(); + +function isWorker() +{ + // It's conceivable that someone would stub out 'document' in a worker so + // also check for childNodes, an arbitrary DOM-related object that is + // meaningless in a WorkerContext. + return (typeof document === 'undefined' || typeof document.childNodes === 'undefined') && !!self.importScripts; +} + +function descriptionQuiet(msg) { description(msg, true); } + +function escapeHTML(text) +{ + return text.replace(/&/g, "&").replace(/PASS ' + escapeHTML(msg) + ''); +} + +function testFailed(msg) +{ + didFailSomeTests = true; + debug('FAIL ' + escapeHTML(msg) + ''); +} + +function areArraysEqual(a, b) +{ + try { + if (a.length !== b.length) + return false; + for (var i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + } catch (ex) { + return false; + } + return true; +} + +function isMinusZero(n) +{ + // the only way to tell 0 from -0 in JS is the fact that 1/-0 is + // -Infinity instead of Infinity + return n === 0 && 1/n < 0; +} + +function isNewSVGTearOffType(v) +{ + return ['[object SVGLength]', '[object SVGLengthList]', '[object SVGPoint]', '[object SVGPointList]', '[object SVGNumber]'].indexOf(""+v) != -1; +} + +function isResultCorrect(actual, expected) +{ + if (expected === 0) + return actual === expected && (1/actual) === (1/expected); + if (actual === expected) + return true; + // http://crbug.com/308818 : The new implementation of SVGListProperties do not necessary return the same wrapper object, so === operator would not work. We compare for their string representation instead. + if (isNewSVGTearOffType(expected) && typeof(expected) == typeof(actual) && actual.valueAsString == expected.valueAsString) + return true; + if (typeof(expected) == "number" && isNaN(expected)) + return typeof(actual) == "number" && isNaN(actual); + if (expected && (Object.prototype.toString.call(expected) == Object.prototype.toString.call([]))) + return areArraysEqual(actual, expected); + return false; +} + +function stringify(v) +{ + if (isNewSVGTearOffType(v)) + return v.valueAsString; + if (v === 0 && 1/v < 0) + return "-0"; + else return "" + v; +} + +function evalAndLog(_a, _quiet) +{ + if (typeof _a != "string") + debug("WARN: tryAndLog() expects a string argument"); + + // Log first in case things go horribly wrong or this causes a sync event. + if (!_quiet) + debug(_a); + + var _av; + try { + _av = eval(_a); + } catch (e) { + testFailed(_a + " threw exception " + e); + } + return _av; +} + +function shouldBe(_a, _b, _quiet) +{ + if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string")) + debug("WARN: shouldBe() expects function or string arguments"); + var _exception; + var _av; + try { + _av = (typeof _a == "function" ? _a() : eval(_a)); + } catch (e) { + _exception = e; + } + var _bv = (typeof _b == "function" ? _b() : eval(_b)); + + if (_exception) + testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception); + else if (isResultCorrect(_av, _bv)) { + if (!_quiet) { + testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b)); + } + } else if (typeof(_av) == typeof(_bv)) + testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + "."); + else + testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ")."); +} + +function shouldBeOneOfValues(_a, _values) +{ + if ((typeof _a != "function" && typeof _a != "string")) + debug("WARN: shouldBeOneOfValues() expects the first argument to be a function or a string"); + if (!Array.isArray(_values)) { + testFailed("The second argument to shouldBeOneOfValues() must be an array of values"); + return; + } + + var _exception; + var _av; + try { + _av = (typeof _a == "function" ? _a() : eval(_a)); + } catch (e) { + _exception = e; + } + + var stringifiedValues = ''; + for (var i = 0; i < _values.length; ++i) { + if (i) { + if (i + 1 == _values.length) + stringifiedValues += ', and '; + else + stringifiedValues += ',' + } + stringifiedValues += "`" + stringify(_values[i]) + "`"; + } + if (_exception) + testFailed(_a + " should be one of " + stringifiedValues + ". Threw exception " + _exception); + else { + var matchedValue = _values.find(function (value) { return isResultCorrect(_av, value); }); + if (matchedValue !== undefined) { + testPassed(_a + " is one of " + stringifiedValues); + } else { + testFailed(_a + " should be one of " + stringifiedValues + ". Was " + stringify(_av) + "."); + } + } +} + +// Execute condition every 5 milliseconds until it succeeds. +function _waitForCondition(condition, completionHandler) +{ + if (condition()) + completionHandler(); + else + setTimeout(_waitForCondition, 5, condition, completionHandler); +} + +function shouldBecomeEqual(_a, _b, completionHandler) +{ + if (typeof _a != "string" || typeof _b != "string") + debug("WARN: shouldBecomeEqual() expects string arguments"); + + function condition() { + var exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + exception = e; + } + var _bv = eval(_b); + if (exception) + testFailed(_a + " should become " + _bv + ". Threw exception " + exception); + if (isResultCorrect(_av, _bv)) { + testPassed(_a + " became " + _b); + return true; + } + return false; + } + + if (!completionHandler) + return new Promise(resolve => setTimeout(_waitForCondition, 0, condition, resolve)); + + setTimeout(_waitForCondition, 0, condition, completionHandler); +} + +function shouldBecomeEqualToString(value, reference, completionHandler) +{ + if (typeof value !== "string" || typeof reference !== "string") + debug("WARN: shouldBecomeEqualToString() expects string arguments"); + var unevaledString = JSON.stringify(reference); + shouldBecomeEqual(value, unevaledString, completionHandler); +} + +function shouldBeType(_a, _type) { + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + + var _typev = eval(_type); + if (_av instanceof _typev) { + testPassed(_a + " is an instance of " + _type); + } else { + testFailed(_a + " is not an instance of " + _type); + } +} + +// Variant of shouldBe()--confirms that result of eval(_to_eval) is within +// numeric _tolerance of numeric _target. +function shouldBeCloseTo(_to_eval, _target, _tolerance, _quiet) +{ + if (typeof _to_eval != "string") { + testFailed("shouldBeCloseTo() requires string argument _to_eval. was type " + typeof _to_eval); + return; + } + if (typeof _target != "number") { + testFailed("shouldBeCloseTo() requires numeric argument _target. was type " + typeof _target); + return; + } + if (typeof _tolerance != "number") { + testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance); + return; + } + + var _result; + try { + _result = eval(_to_eval); + } catch (e) { + testFailed(_to_eval + " should be within " + _tolerance + " of " + + _target + ". Threw exception " + e); + return; + } + + if (typeof(_result) != typeof(_target)) { + testFailed(_to_eval + " should be of type " + typeof _target + + " but was of type " + typeof _result); + } else if (Math.abs(_result - _target) <= _tolerance) { + if (!_quiet) { + testPassed(_to_eval + " is within " + _tolerance + " of " + _target); + } + } else { + testFailed(_to_eval + " should be within " + _tolerance + " of " + _target + + ". Was " + _result + "."); + } +} + +function shouldNotBe(_a, _b, _quiet) +{ + if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string")) + debug("WARN: shouldNotBe() expects function or string arguments"); + var _exception; + var _av; + try { + _av = (typeof _a == "function" ? _a() : eval(_a)); + } catch (e) { + _exception = e; + } + var _bv = (typeof _b == "function" ? _b() : eval(_b)); + + if (_exception) + testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception); + else if (!isResultCorrect(_av, _bv)) { + if (!_quiet) { + testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b)); + } + } else + testFailed(_a + " should not be " + _bv + "."); +} + +function shouldBecomeDifferent(_a, _b, completionHandler) +{ + if (typeof _a != "string" || typeof _b != "string") + debug("WARN: shouldBecomeDifferent() expects string arguments"); + + function condition() { + var exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + exception = e; + } + var _bv = eval(_b); + if (exception) + testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + exception); + if (!isResultCorrect(_av, _bv)) { + testPassed(_a + " became different from " + _b); + return true; + } + return false; + } + + if (!completionHandler) + return new Promise(resolve => setTimeout(_waitForCondition, 0, condition, resolve)); + + setTimeout(_waitForCondition, 0, condition, completionHandler); +} + +function shouldBeTrue(a, quiet) { shouldBe(a, "true", quiet); } +function shouldBeTrueQuiet(a) { shouldBe(a, "true", true); } +function shouldBeFalse(a, quiet) { shouldBe(a, "false", quiet); } +function shouldBeNaN(a, quiet) { shouldBe(a, "NaN", quiet); } +function shouldBeNull(a, quiet) { shouldBe(a, "null", quiet); } +function shouldBeZero(a, quiet) { shouldBe(a, "0", quiet); } + +function shouldBeEqualToString(a, b) +{ + if (typeof a !== "string" || typeof b !== "string") + debug("WARN: shouldBeEqualToString() expects string arguments"); + var unevaledString = JSON.stringify(b); + shouldBe(a, unevaledString); +} + +function shouldBeEqualToNumber(a, b) +{ + if (typeof a !== "string" || typeof b !== "number") + debug("WARN: shouldBeEqualToNumber() expects a string and a number arguments"); + var unevaledString = JSON.stringify(b); + shouldBe(a, unevaledString); +} + +function shouldBeEmptyString(a) { shouldBeEqualToString(a, ""); } + +function shouldEvaluateTo(actual, expected) { + // A general-purpose comparator. 'actual' should be a string to be + // evaluated, as for shouldBe(). 'expected' may be any type and will be + // used without being eval'ed. + if (expected == null) { + // Do this before the object test, since null is of type 'object'. + shouldBeNull(actual); + } else if (typeof expected == "undefined") { + shouldBeUndefined(actual); + } else if (typeof expected == "function") { + // All this fuss is to avoid the string-arg warning from shouldBe(). + try { + var actualValue = eval(actual); + } catch (e) { + testFailed("Evaluating " + actual + ": Threw exception " + e); + return; + } + shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'", + "'" + expected.toString().replace(/\n/g, "") + "'"); + } else if (typeof expected == "object") { + shouldBeTrue(actual + " == '" + expected + "'"); + } else if (typeof expected == "string") { + shouldBe(actual, expected); + } else if (typeof expected == "boolean") { + shouldBe("typeof " + actual, "'boolean'"); + if (expected) + shouldBeTrue(actual); + else + shouldBeFalse(actual); + } else if (typeof expected == "number") { + shouldBe(actual, stringify(expected)); + } else { + debug(expected + " is unknown type " + typeof expected); + shouldBeTrue(actual, "'" +expected.toString() + "'"); + } +} + +function shouldBeNonZero(_a) +{ + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + + if (_exception) + testFailed(_a + " should be non-zero. Threw exception " + _exception); + else if (_av != 0) + testPassed(_a + " is non-zero."); + else + testFailed(_a + " should be non-zero. Was " + _av); +} + +function shouldBeNonNull(_a) +{ + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + + if (_exception) + testFailed(_a + " should be non-null. Threw exception " + _exception); + else if (_av != null) + testPassed(_a + " is non-null."); + else + testFailed(_a + " should be non-null. Was " + _av); +} + +function shouldBeUndefined(_a) +{ + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + + if (_exception) + testFailed(_a + " should be undefined. Threw exception " + _exception); + else if (typeof _av == "undefined") + testPassed(_a + " is undefined."); + else + testFailed(_a + " should be undefined. Was " + _av); +} + +function shouldBeDefined(_a) +{ + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + + if (_exception) + testFailed(_a + " should be defined. Threw exception " + _exception); + else if (_av !== undefined) + testPassed(_a + " is defined."); + else + testFailed(_a + " should be defined. Was " + _av); +} + +function shouldBeGreaterThan(_a, _b) { + if (typeof _a != "string" || typeof _b != "string") + debug("WARN: shouldBeGreaterThan expects string arguments"); + + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + var _bv = eval(_b); + + if (_exception) + testFailed(_a + " should be > " + _b + ". Threw exception " + _exception); + else if (typeof _av == "undefined" || _av <= _bv) + testFailed(_a + " should be > " + _b + ". Was " + _av + " (of type " + typeof _av + ")."); + else + testPassed(_a + " is > " + _b); +} + +function shouldBeGreaterThanOrEqual(_a, _b) { + if (typeof _a != "string" || typeof _b != "string") + debug("WARN: shouldBeGreaterThanOrEqual expects string arguments"); + + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + var _bv = eval(_b); + + if (_exception) + testFailed(_a + " should be >= " + _b + ". Threw exception " + _exception); + else if (typeof _av == "undefined" || _av < _bv) + testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " + typeof _av + ")."); + else + testPassed(_a + " is >= " + _b); +} + +function shouldBeLessThanOrEqual(_a, _b) { + if (typeof _a != "string" || typeof _b != "string") + debug("WARN: shouldBeLessThanOrEqual expects string arguments"); + + var _exception; + var _av; + try { + _av = eval(_a); + } catch (e) { + _exception = e; + } + var _bv = eval(_b); + + if (_exception) + testFailed(_a + " should be <= " + _b + ". Threw exception " + _exception); + else if (typeof _av == "undefined" || _av > _bv) + testFailed(_a + " should be <= " + _b + ". Was " + _av + " (of type " + typeof _av + ")."); + else + testPassed(_a + " is <= " + _b); +} + +function expectTrue(v, msg) { + if (v) { + testPassed(msg); + } else { + testFailed(msg); + } +} + +function shouldNotThrow(_a, _message) { + try { + typeof _a == "function" ? _a() : eval(_a); + testPassed((_message ? _message : _a) + " did not throw exception."); + } catch (e) { + testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + "."); + } +} + +function shouldThrow(_a, _e, _message) +{ + var _exception; + var _av; + try { + _av = typeof _a == "function" ? _a() : eval(_a); + } catch (e) { + _exception = e; + } + + var _ev; + if (_e) + _ev = eval(_e); + + if (_exception) { + if (typeof _e == "undefined" || _exception == _ev) + testPassed((_message ? _message : _a) + " threw exception " + _exception + "."); + else + testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + _exception + "."); + } else if (typeof _av == "undefined") + testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined."); + else + testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + "."); +} + +function shouldBeNow(a, delta) +{ + // Right now, V8 and Chromium / Blink use two different clock + // implementations. On Windows, the implementations are non-trivial and can + // be slightly out of sync. The delta is intended to compensate for that. + // + // FIXME: reconsider this when the V8 and Blink clocks get unified, see http://crbug.com/324110 + if (delta === undefined) + delta = 1000; + + for (var i = 0; i < 1000; ++i) { + var startDate = Date.now(); + var av = eval(a); + var date = av.valueOf(); + var endDate = Date.now(); + + // On some occasions such as NTP updates, the current time can go + // backwards. This should only happen rarely, so we can get away with + // retrying the test a few times if we detect the time going backwards. + if (startDate > endDate) + continue; + + if (typeof date !== "number") { + testFailed(a + " is not a number or a Date. Got " + av); + return; + } + if (date < startDate - delta) { + testFailed(a + " is not the curent time. Got " + av + " which is " + (startDate - date) / 1000 + " seconds in the past."); + return; + } + if (date > endDate + delta) { + testFailed(a + " is not the current time. Got " + av + " which is " + (date - endDate) / 1000 + " seconds in the future."); + return; + } + + testPassed(a + " is equivalent to Date.now()."); + return; + } + testFailed(a + " cannot be tested against the current time. The clock is going backwards too often."); +} + +function expectError() +{ + if (expectingError) { + testFailed("shouldHaveError() called twice before an error occurred!"); + } + expectingError = true; +} + +function shouldReject(_a, _message) +{ + return shouldRejectWithErrorName(_a, undefined, _message); +} + +function shouldRejectWithErrorName(_a, _name, _message) +{ + var _exception; + var _av; + try { + _av = typeof _a == "function" ? _a() : eval(_a); + } catch (e) { + testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + "."); + return Promise.resolve(); + } + + return _av.then(function(result) { + testFailed((_message ? _message : _a) + " should reject promise. Resolved with " + result + "."); + }, function(error) { + if (_name === undefined) { + testPassed((_message ? _message : _a) + " rejected promise."); + } else if (error['name'] === _name) { + // FIXME: Remove the extra space and '.' (DOMException descriptions already end with periods) then rebase tests. + testPassed((_message ? _message : _a) + " rejected promise with " + error + "."); + } else + testFailed((_message ? _message : _a) + " should reject promise with " + _name + ". Rejected with " + error['name'] + " instead."); + }); +} + +function shouldThrowErrorName(_a, _name) +{ + var _exception; + try { + typeof _a == "function" ? _a() : eval(_a); + } catch (e) { + _exception = e; + } + + if (_exception) { + if (_exception.name == _name) + testPassed(_a + " threw exception " + _exception + "."); + else + testFailed(_a + " should throw a " + _name + ". Threw a " + _exception.name + "."); + } else + testFailed(_a + " should throw a " + _name + ". Did not throw."); +} + +function shouldHaveHadError(message) +{ + if (expectingError) { + testFailed("No error thrown between expectError() and shouldHaveHadError()"); + return; + } + + if (expectedErrorMessage) { + if (!message) + testPassed("Got expected error"); + else if (expectedErrorMessage.indexOf(message) !== -1) + testPassed("Got expected error: '" + message + "'"); + else + testFailed("Unexpected error '" + message + "'"); + expectedErrorMessage = undefined; + return; + } + + testFailed("expectError() not called before shouldHaveHadError()"); +} + +function gc() { + if (typeof GCController !== "undefined") + GCController.collect(); + else { + var gcRec = function (n) { + if (n < 1) + return {}; + var temp = {i: "ab" + i + (i / 100000)}; + temp += "foo"; + gcRec(n-1); + }; + for (var i = 0; i < 1000; i++) + gcRec(10); + } +} + +function minorGC() { + if (typeof GCController !== "undefined") + GCController.minorCollect(); + else + testFailed("Minor GC is available only when you enable the --expose-gc option in V8."); +} + +function isSuccessfullyParsed() +{ + // FIXME: Remove this and only report unexpected syntax errors. + successfullyParsed = !unexpectedErrorMessage; + shouldBeTrue("successfullyParsed"); + if (didFailSomeTests) + debug("Some tests failed."); + debug('
TEST COMPLETE'); +} + +// It's possible for an async test to call finishJSTest() before js-test-post.js +// has been parsed. +function finishJSTest() +{ + wasFinishJSTestCalled = true; + if (!self.wasPostTestScriptParsed) + return; + isSuccessfullyParsed(); + moveForeignObjectToTopIfNeeded(); + if (self.jsTestIsAsync && self.testRunner) + testRunner.notifyDone(); +} + +function areObjectsEqual(a, b) { + for (var property in a) { + if (!b.hasOwnProperty(property)) + return false; + + switch (typeof (a[property])) { + case 'function': + if (typeof b[property] == 'undefined' || a[property].toString() != b[property].toString()) + return false; + break; + case 'object': + if (!areObjectsEqual(a, b)) + return false; + break; + default: + if (a[property] != b[property]) + return false; + } + } + + for (var property in b) { + if (!a.hasOwnProperty(property)) + return false; + } + + return true; +}; + +function startWorker(testScriptURL) +{ + self.jsTestIsAsync = true; + debug('Starting worker: ' + testScriptURL); + var worker = new Worker(testScriptURL); + worker.onmessage = function(event) + { + var workerPrefix = "[Worker] "; + if (event.data.length < 5 || event.data.charAt(4) != ':') { + debug(workerPrefix + event.data); + return; + } + var code = event.data.substring(0, 4); + var payload = workerPrefix + event.data.substring(5); + if (code == "PASS") + testPassed(payload); + else if (code == "FAIL") + testFailed(payload); + else if (code == "DESC") + description(payload); + else if (code == "DONE") + finishJSTest(); + else + debug(workerPrefix + event.data); + }; + + worker.onerror = function(event) + { + debug('Got error from worker: ' + event.message); + finishJSTest(); + }; + + return worker; +} + +if (isWorker()) { + var workerPort = self; + description = function(msg, quiet) { + workerPort.postMessage('DESC:' + msg); + }; + testFailed = function(msg) { + workerPort.postMessage('FAIL:' + msg); + }; + testPassed = function(msg) { + workerPort.postMessage('PASS:' + msg); + }; + finishJSTest = function() { + workerPort.postMessage('DONE:'); + }; + debug = function(msg) { + workerPort.postMessage(msg); + }; +} + +function downgradeReferrerCallback(policy, host) { + let scriptElement = document.createElement("script"); + scriptElement.src = "http://".concat(host, ":8000/referrer-policy/resources/script.py"); + scriptElement.referrerPolicy = policy; + document.body.appendChild(scriptElement); +} diff --git a/MotionMark/unit-tests/test-animator.html b/MotionMark/unit-tests/test-animator.html new file mode 100644 index 0000000..59091db --- /dev/null +++ b/MotionMark/unit-tests/test-animator.html @@ -0,0 +1,72 @@ + + + + + + + + diff --git a/MotionMark/unit-tests/test-fixed-controller.html b/MotionMark/unit-tests/test-fixed-controller.html new file mode 100644 index 0000000..aa5dfe2 --- /dev/null +++ b/MotionMark/unit-tests/test-fixed-controller.html @@ -0,0 +1,59 @@ + + + + + + + diff --git a/MotionMark/unit-tests/test-ramp-controller.html b/MotionMark/unit-tests/test-ramp-controller.html new file mode 100644 index 0000000..6ae7933 --- /dev/null +++ b/MotionMark/unit-tests/test-ramp-controller.html @@ -0,0 +1,10 @@ + + + + + + + diff --git a/MotionMark/unit-tests/test-regression.html b/MotionMark/unit-tests/test-regression.html new file mode 100644 index 0000000..0e1bef4 --- /dev/null +++ b/MotionMark/unit-tests/test-regression.html @@ -0,0 +1,272 @@ + + + + + + + diff --git a/MotionMark/unit-tests/test-spiral-iterator.html b/MotionMark/unit-tests/test-spiral-iterator.html new file mode 100644 index 0000000..c9bb47f --- /dev/null +++ b/MotionMark/unit-tests/test-spiral-iterator.html @@ -0,0 +1,29 @@ + + + + + + +