Simplify the test harness
authorjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 Jan 2016 23:02:56 +0000 (23:02 +0000)
committerjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 Jan 2016 23:02:56 +0000 (23:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152562

Reviewed by Simon Fraser.

All of the benchmarks use the default Animator(). Don't require new tests
to pass a new instance, and instead just make one in the Benchmark constructor.

* Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js:
* Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
* Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:
* Animometer/tests/master/resources/canvas-tests.js:
* Animometer/tests/misc/resources/canvas-electrons.js:
* Animometer/tests/misc/resources/canvas-stars.js:
* Animometer/tests/misc/resources/compositing-transforms.js:
* Animometer/tests/resources/main.js:
* Animometer/tests/simple/resources/simple-canvas-paths.js:
* Animometer/tests/template/resources/template-canvas.js:
* Animometer/tests/template/resources/template-css.js:
* Animometer/tests/template/resources/template-svg.js:
* Animometer/tests/text/resources/layering-text.js:
* Animometer/tests/text/resources/text-boxes.js:

Refactor the template.

* Animometer/tests/template/resources/template-canvas.js:
* Animometer/tests/template/resources/template-css.js:
* Animometer/tests/template/resources/template-svg.js:
* Animometer/tests/template/template-canvas.html:
* Animometer/tests/template/template-css.html:
* Animometer/tests/template/template-svg.html:

Refactor the SVG suite.

* Animometer/tests/bouncing-particles/bouncing-svg-images.html: Move scripts to the end.
* Animometer/tests/bouncing-particles/bouncing-svg-shapes.html: Ditto.

* Animometer/tests/bouncing-particles/bouncing-canvas-shapes.html: Remove extraneous includes
to stage.js.
* Animometer/tests/text/text-boxes.html: Ditto.

BouncingCanvasParticlesBenchmark is not necessary. Use Benchmark directly when subclassing.
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js: Remove
BouncingCanvasParticlesBenchmark.
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js: Use Benchmark.
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js: Ditto.

* Animometer/tests/bouncing-particles/resources/bouncing-svg-particles.js: Require the shape
in the constructor instead of having subclasses set the private variable.

* Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js: Refactor.
* Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:

Refactor the HTML suite.

Move scripts to the end.
* Animometer/tests/bouncing-particles/bouncing-css-images.html:
* Animometer/tests/bouncing-particles/bouncing-css-shapes.html:
* Animometer/tests/text/layering-text.html:
* Animometer/tests/text/text-boxes.html:

Refactor to use the new variables.
* Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
* Animometer/tests/text/resources/layering-text.js:
* Animometer/tests/text/resources/text-boxes.js:

Refactor the bouncing canvas tests.

* Animometer/tests/bouncing-particles/bouncing-canvas-images.html: Move scripts to the end.
* Animometer/tests/bouncing-particles/bouncing-canvas-shapes.html: Move scripts to the end.

* Animometer/tests/bouncing-particles/resources/bouncing-particles.js: Promote a few
properties to "public" since they are used by subclasses.
(BouncingParticlesStage): Fix the constructor, which was missing "this". Make particles
"public" for subclasses.
(BouncingParticlesStage.initialize): Fix the max velocity, which was accidentally changed.
* Animometer/tests/misc/resources/compositing-transforms.js: Refactor.

* Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js:
BouncingCanvasParticlesAnimator is no longer needed.
(BouncingCanvasParticle): Change constructor to take a shape as a parameter instead of
having subclasses set the variable.

* Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js: Refactor.
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js: Refactor.

Move example/ files into misc/.

* Animometer/tests/misc/canvas-electrons.html: Renamed from PerformanceTests/Animometer/tests/examples/canvas-electrons.html.
* Animometer/tests/misc/canvas-stars.html: Renamed from PerformanceTests/Animometer/tests/examples/canvas-stars.html.
* Animometer/tests/misc/resources/canvas-electrons.js: Renamed from PerformanceTests/Animometer/tests/examples/resources/canvas-electrons.js.
* Animometer/tests/misc/resources/canvas-stars.js: Renamed from PerformanceTests/Animometer/tests/examples/resources/canvas-stars.js.

* Animometer/resources/debug-runner/tests.js: Update test URLs.

Refactor miscellaneous suite.

* Animometer/tests/bouncing-particles/resources/bouncing-particles.js:
Remove BouncingParticlesAnimator and BouncingParticleBenchmark, which are
not needed.
(tune): Remove console assert.
* Animometer/tests/resources/main.js: Add Rotater back in from stage.js.

* Animometer/tests/examples/resources/canvas-electrons.js: Remove CanvasElectronsAnimator.
* Animometer/tests/examples/resources/canvas-stars.js: Remove CanvasStarsAnimator.
* Animometer/tests/misc/resources/compositing-transforms.js:
* Animometer/tests/examples/canvas-electrons.html: Move scripts to the end.
* Animometer/tests/examples/canvas-stars.html: Ditto.
* Animometer/tests/misc/compositing-transforms.html: Ditto.

Refactor the simple suite.

* Animometer/tests/master/resources/canvas-stage.js:
(tune): Remove coordinateMaximum since it is not needed in any
of the master tests.
* Animometer/tests/simple/resources/simple-canvas.js:
SimpleCanvasAnimator and SimpleCanvasBenchmark are no longer
needed.
(tune): Manage the objects differently, but instead of duplicating
all of SimpleCanvasStage here, just replace tune(). Include
coordinateMaximum, and remove items from the end of the list
instead of the beginning.
(StageBenchmark.call.createAnimator): Deleted.
(StageBenchmark.call): Deleted.
* Animometer/tests/simple/resources/simple-canvas-paths.js:
* Animometer/tests/simple/simple-canvas-paths.html: Move
scripts to the end.

Get rid of stage.js, StageAnimator, and StageBenchmark. Don't have the progress bar update during the test.

* Animometer/resources/debug-runner/animometer.js:
(initialize): Move the setting of testsCount to the debug runner.
(didRunTest): Nicer name.
* Animometer/resources/debug-runner/benchmark-runner.js:
(BenchmarkRunner.prototype._runBenchmarkAndRecordResults): Don't pass in the progress bar to benchmarks.
* Animometer/resources/extensions.js:
(ProgressBar): Refactor. Make variables "private". Resetting the progress when instantiating.
(ProgressBar.prototype.incrementRange): This is called every time a benchmark completes.
* Animometer/resources/runner/animometer.js:
(window.benchmarkRunnerClient.initialize): Remove unneeded setting of testsCount.
* Animometer/resources/strings.js: These are no longer needed.
* Animometer/tests/master/canvas-stage.html: Remove script inclusion. Other tests will follow.
* Animometer/tests/master/resources/canvas-tests.js: Use Benchmark instead of StageBenchmark.
* Animometer/tests/resources/main.js: Messages are no longer needed
(Animator.prototype._shouldRequestAnotherFrame): Rename from animate(), since this method returns a boolean
indicating whether another frame should be requested. Collapse the logic from StageAnimator into animateLoop.
(BenchmarkState.prototype.currentStage): Deleted.
(BenchmarkState.prototype.currentMessage): Deleted.
(BenchmarkState.prototype.currentProgress): Deleted.
(Animator.prototype.animate): Deleted.
(Animator.prototype.animateLoop): The stage is animated only when we have another frame to draw.
(Benchmark.prototype.record): No need to update the progress bar.
* Animometer/tests/resources/stage.js: Removed. Rotater will appear in a later patch, in main.js.

* Animometer/resources/debug-runner/benchmark-runner.js:
(BenchmarkRunner.prototype._runBenchmarkAndRecordResults): Each test is run as a benchmark.
Remove the call to runBenchmark by merging the options here, and calling benchmark.run()
directly.

Make the class relationships more easily understandable. The benchmark owns the stage,
animator, and options. Make the stage and animator no longer have their own references to
the options. Make Stage a first-class citizen by promoting it to main.js. Later patches
will try to get rid of stage.js altogether.
* Animometer/tests/resources/main.js:
(Stage): Moved from stage.js.
(Animator): Don't pass in benchmark and options in its constructor. It will get initialized
by benchmark-related parameters in initialize().
(Animator.prototype.initialize): Add a back-reference to benchmark and cache an option.
(Animator.prototype.get benchmark):
(Animator.prototype.animate): Refactor to use the cached option, to remove its dependency on
the options dictionary.
(Benchmark): Require all benchmarks to have a stage and animator. The instance will initialize
them.
(Benchmark.prototype.get options):
(Benchmark.prototype.get stage): BenchmarkStates.stages will need to be renamed to avoid confusion.
(Benchmark.prototype.get animator):
(Benchmark.prototype.start):
(Benchmark.prototype.update): Ask the stage directly to tune or clear instead of adding another
level of indirection.
(window.runBenchmark): Deleted. Remove the need for a benchmarkClient. Also remove the standalone
path, since tests can be individually selected, and remove the need for runBenchmark since that is
handled in BenchmarkRunner._runBenchmarkAndRecordResults.
* Animometer/tests/resources/stage.js:
(Stage): Deleted. Moved to main.js.
(StageBenchmark): What's left is updating the progress bar; to be removed.
(StageAnimator): What's left can be folded in Animator.

Refactor master suite.
* Animometer/tests/master/resources/canvas-stage.js: This now only has SimpleCanvasStage.
(animate): Push the clearRect() into each stage.
(complexity):
(StageBenchmark.call.createAnimator): Deleted.
(StageBenchmark.call): Deleted.
* Animometer/tests/master/resources/canvas-tests.js: SimpleCanvasPathStrokeStage is no longer needed.
(CanvasLineSegment.prototype.draw):
(CanvasArc):
(CanvasLinePoint): Remove the draw call because depending on its index it either needs to be moveTo
or lineTo, and it is otherwise a very small draw operation that doesn't need the overhead of the
function call. Do all of the drawing through the stage.

Refactor the subclass pattern. Introduce Utilities.createSubclass().

* Animometer/resources/debug-runner/benchmark-runner.js:
* Animometer/resources/extensions.js:
(window.Utilities.createSubclass): Takes the super class, a function representing
the class's constructor, and additional methods to attach to the new class's
prototype object.
* Animometer/tests/text/text-boxes.html: Remove unneeded reference to utilities.js.

Refactor tests.
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js:
* Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js:
* Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
* Animometer/tests/bouncing-particles/resources/bouncing-particles.js:
* Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js:
* Animometer/tests/bouncing-particles/resources/bouncing-svg-particles.js:
* Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:
* Animometer/tests/examples/resources/canvas-electrons.js:
* Animometer/tests/examples/resources/canvas-stars.js:
* Animometer/tests/master/resources/canvas-stage.js:
* Animometer/tests/master/resources/canvas-tests.js:
* Animometer/tests/misc/resources/compositing-transforms.js:
* Animometer/tests/resources/stage.js:
* Animometer/tests/simple/resources/simple-canvas-paths.js:
* Animometer/tests/simple/resources/simple-canvas.js:
* Animometer/tests/template/resources/template-canvas.js:
* Animometer/tests/template/resources/template-css.js:
* Animometer/tests/template/resources/template-svg.js:
* Animometer/tests/text/resources/layering-text.js: Reorder some of the methods
and properties since they rely on each other.
* Animometer/tests/text/resources/text-boxes.js:

* Animometer/resources/debug-runner/animometer.js: Arrange calls
in the order they are evoked.
* Animometer/resources/debug-runner/benchmark-runner.js:
(BenchmarkRunnerState.prototype.next): Get rid of return value since
no caller to next() uses it.
(BenchmarkRunnerState.prototype.prepareCurrentTest): Refactor the
promise to resolve simply when onload() is called instead of
looking for #stage.
(BenchmarkRunner.prototype._runTestAndRecordResults): Suite.run
simply calls runBenchmark(). Call it directly rather than through
the Suite.
(BenchmarkRunner.prototype.step): Remove unused parameter in
resolve callback.
(BenchmarkRunner.prototype.runMultipleIterations): Use this instead
of self since it is outside of the closure which needed the self
variable.
(resolveIfReady): Deleted.
(BenchmarkRunner.prototype.waitForElement): Deleted.
* Animometer/resources/runner/tests.js: prepare() and run() are
no longer needed.
(Suite.prototype.prepare): Deleted.
(Suite.prototype.run): Deleted.
* Animometer/tests/master/canvas-stage.html: Move all scripts to
the end of the page.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194520 268f45cc-cd09-0410-ab3c-d52691b4dbfc

49 files changed:
PerformanceTests/Animometer/resources/debug-runner/animometer.js
PerformanceTests/Animometer/resources/debug-runner/benchmark-runner.js
PerformanceTests/Animometer/resources/debug-runner/tests.js
PerformanceTests/Animometer/resources/extensions.js
PerformanceTests/Animometer/resources/runner/animometer.js
PerformanceTests/Animometer/resources/runner/tests.js
PerformanceTests/Animometer/resources/strings.js
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-canvas-images.html
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-canvas-shapes.html
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-css-images.html
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-css-shapes.html
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-svg-images.html
PerformanceTests/Animometer/tests/bouncing-particles/bouncing-svg-shapes.html
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-css-images.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-particles.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-svg-particles.js
PerformanceTests/Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js
PerformanceTests/Animometer/tests/examples/resources/canvas-electrons.js [deleted file]
PerformanceTests/Animometer/tests/examples/resources/canvas-stars.js [deleted file]
PerformanceTests/Animometer/tests/master/canvas-stage.html
PerformanceTests/Animometer/tests/master/resources/canvas-stage.js
PerformanceTests/Animometer/tests/master/resources/canvas-tests.js
PerformanceTests/Animometer/tests/misc/canvas-electrons.html [moved from PerformanceTests/Animometer/tests/examples/canvas-electrons.html with 91% similarity]
PerformanceTests/Animometer/tests/misc/canvas-stars.html [moved from PerformanceTests/Animometer/tests/examples/canvas-stars.html with 91% similarity]
PerformanceTests/Animometer/tests/misc/compositing-transforms.html
PerformanceTests/Animometer/tests/misc/resources/canvas-electrons.js [new file with mode: 0644]
PerformanceTests/Animometer/tests/misc/resources/canvas-stars.js [new file with mode: 0644]
PerformanceTests/Animometer/tests/misc/resources/compositing-transforms.js
PerformanceTests/Animometer/tests/resources/main.js
PerformanceTests/Animometer/tests/resources/stage.js [deleted file]
PerformanceTests/Animometer/tests/simple/resources/simple-canvas-paths.js
PerformanceTests/Animometer/tests/simple/resources/simple-canvas.js
PerformanceTests/Animometer/tests/simple/simple-canvas-paths.html
PerformanceTests/Animometer/tests/template/resources/template-canvas.js
PerformanceTests/Animometer/tests/template/resources/template-css.js
PerformanceTests/Animometer/tests/template/resources/template-svg.js
PerformanceTests/Animometer/tests/template/template-canvas.html
PerformanceTests/Animometer/tests/template/template-css.html
PerformanceTests/Animometer/tests/template/template-svg.html
PerformanceTests/Animometer/tests/text/layering-text.html
PerformanceTests/Animometer/tests/text/resources/layering-text.js
PerformanceTests/Animometer/tests/text/resources/text-boxes.js
PerformanceTests/Animometer/tests/text/text-boxes.html
PerformanceTests/ChangeLog

index 48fd067..48d523a 100644 (file)
@@ -2,15 +2,21 @@ Utilities.extendObject(window.benchmarkRunnerClient, {
     testsCount: null,
     progressBar: null,
 
-    didRunTest: function ()
+    initialize: function(suites, options)
     {
-        this.progressBar.incRange();
+        this.testsCount = this.iterationCount * suites.reduce(function (count, suite) { return count + suite.tests.length; }, 0);
+        this.options = options;
     },
-    
+
     willStartFirstIteration: function ()
     {
         this.results = new ResultsDashboard();
         this.progressBar = new ProgressBar(document.getElementById("progress-completed"), this.testsCount);
+    },
+
+    didRunTest: function()
+    {
+        this.progressBar.incrementRange();
     }
 });
 
@@ -30,7 +36,7 @@ window.optionsManager =
             return formElement.checked;
         return formElement.value;
     },
-    
+
     updateUIFromLocalStorage: function()
     {
         var formElements = document.forms["benchmark-options"].elements;
@@ -56,7 +62,7 @@ window.optionsManager =
     updateLocalStorageFromUI: function()
     {
         var formElements = document.forms["benchmark-options"].elements;
-        var options = {};        
+        var options = {};
 
         for (var i = 0; i < formElements.length; ++i) {
             var formElement = formElements[i];
@@ -69,10 +75,10 @@ window.optionsManager =
                 options[name] = formElement.checked;
             else if (type == "radio")
                 options[name] = formElements[name].value;
-    
+
             localStorage.setItem(name, options[name]);
         }
-        
+
         return options;
     }
 }
@@ -83,12 +89,12 @@ window.suitesManager =
     {
         return document.querySelector("#suites > .tree");
     },
-    
+
     _suitesElements: function()
     {
         return document.querySelectorAll("#suites > ul > li");
     },
-    
+
     _checkboxElement: function(element)
     {
         return element.querySelector("input[type='checkbox']:not(.expand-button)");
@@ -103,7 +109,7 @@ window.suitesManager =
     {
         return document.querySelectorAll("#suites input[type='number']");
     },
-        
+
     _localStorageNameForTest: function(suiteName, testName)
     {
         return suiteName + "/" + testName;
@@ -125,17 +131,17 @@ window.suitesManager =
     {
         var suitesElements = this._suitesElements();
         var startButton = document.querySelector("#intro button");
-        
+
         for (var i = 0; i < suitesElements.length; ++i) {
             var suiteElement = suitesElements[i];
             var suiteCheckbox = this._checkboxElement(suiteElement);
-            
+
             if (suiteCheckbox.checked) {
                 startButton.disabled = false;
                 return;
             }
         }
-    
+
         startButton.disabled = true;
     },
 
@@ -144,7 +150,7 @@ window.suitesManager =
         var selected = event.target.checked;
         event.target.testsElements.forEach(function(testElement) {
             var testCheckbox = this._checkboxElement(testElement);
-            testCheckbox.checked = selected;        
+            testCheckbox.checked = selected;
         }, this);
         this._updateStartButtonState();
     },
@@ -201,7 +207,7 @@ window.suitesManager =
             }, this);
         }, this);
     },
-    
+
     updateEditsElementsState: function()
     {
         var editsElements = this._editsElements();
@@ -224,17 +230,17 @@ window.suitesManager =
     updateUIFromLocalStorage: function()
     {
         var suitesElements = this._suitesElements();
-        
+
         for (var i = 0; i < suitesElements.length; ++i) {
             var suiteElement = suitesElements[i];
             var suiteCheckbox = this._checkboxElement(suiteElement);
             var suite = suiteCheckbox.suite;
-            
+
             suiteCheckbox.testsElements.forEach(function(testElement) {
                 var testCheckbox = this._checkboxElement(testElement);
                 var testEdit = this._editElement(testElement);
                 var test = testCheckbox.test;
-                
+
                 var str = localStorage.getItem(this._localStorageNameForTest(suite.name, test.name));
                 if (str === null)
                     return;
@@ -246,7 +252,7 @@ window.suitesManager =
 
             this._updateSuiteCheckboxState(suiteCheckbox);
         }
-        
+
         this._updateStartButtonState();
     },
 
@@ -254,7 +260,7 @@ window.suitesManager =
     {
         var suitesElements = this._suitesElements();
         var suites = [];
-        
+
         for (var i = 0; i < suitesElements.length; ++i) {
             var suiteElement = suitesElements[i];
             var suiteCheckbox = this._checkboxElement(suiteElement);
@@ -265,13 +271,13 @@ window.suitesManager =
                 var testCheckbox = this._checkboxElement(testElement);
                 var testEdit = this._editElement(testElement);
                 var test = testCheckbox.test;
-                
+
                 if (testCheckbox.checked) {
                     test.complexity = testEdit.value;
                     tests.push(test);
                 }
 
-                var value = { checked: testCheckbox.checked, complexity: testEdit.value }; 
+                var value = { checked: testCheckbox.checked, complexity: testEdit.value };
                 localStorage.setItem(this._localStorageNameForTest(suite.name, test.name), JSON.stringify(value));
             }, this);
 
@@ -281,7 +287,7 @@ window.suitesManager =
 
         return suites;
     },
-    
+
     updateLocalStorageFromJSON: function(iterationResults)
     {
         for (var suiteName in iterationResults[Strings.json.results.suites]) {
index 0f793c5..376b51b 100644 (file)
@@ -6,48 +6,49 @@ function BenchmarkRunnerState(suites)
     this.next();
 }
 
-BenchmarkRunnerState.prototype.currentSuite = function()
-{
-    return this._suites[this._suiteIndex];
-};
-
-BenchmarkRunnerState.prototype.currentTest = function()
-{
-    var suite = this.currentSuite();
-    return suite ? suite.tests[this._testIndex] : null;
-};
-
-BenchmarkRunnerState.prototype.isFirstTest = function()
-{
-    return !this._testIndex;
-};
-
-BenchmarkRunnerState.prototype.next = function()
-{
-    this._testIndex++;
-
-    var suite = this._suites[this._suiteIndex];
-    if (suite && this._testIndex < suite.tests.length)
-        return this;
-
-    this._testIndex = 0;
-    do {
-        this._suiteIndex++;
-    } while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled);
+BenchmarkRunnerState.prototype = {
+    currentSuite: function()
+    {
+        return this._suites[this._suiteIndex];
+    },
+
+    currentTest: function()
+    {
+        var suite = this.currentSuite();
+        return suite ? suite.tests[this._testIndex] : null;
+    },
+
+    isFirstTest: function()
+    {
+        return !this._testIndex;
+    },
+
+    next: function()
+    {
+        this._testIndex++;
+
+        var suite = this._suites[this._suiteIndex];
+        if (suite && this._testIndex < suite.tests.length)
+            return;
+
+        this._testIndex = 0;
+        do {
+            this._suiteIndex++;
+        } while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled);
+    },
+
+    prepareCurrentTest: function(runner, frame)
+    {
+        var test = this.currentTest();
+        var promise = new SimplePromise;
 
-    return this;
-};
+        frame.onload = function() {
+            promise.resolve();
+        };
 
-BenchmarkRunnerState.prototype.prepareCurrentTest = function(runner, frame)
-{
-    var suite = this.currentSuite();
-    var test = this.currentTest();
-    var promise = new SimplePromise;
-    frame.onload = function() {
-        suite.prepare(runner, frame.contentWindow, frame.contentDocument).then(function(result) { promise.resolve(result); });
+        frame.src = "tests/" + test.url;
+        return promise;
     }
-    frame.src = "tests/" + test.url;
-    return promise;
 };
 
 function BenchmarkRunner(suites, frameContainer, client)
@@ -57,128 +58,119 @@ function BenchmarkRunner(suites, frameContainer, client)
     this._frameContainer = frameContainer;
 }
 
-BenchmarkRunner.prototype.waitForElement = function(selector)
-{
-    var promise = new SimplePromise;
-    var contentDocument = this._frame.contentDocument;
-
-    function resolveIfReady() {
-        var element = contentDocument.querySelector(selector);
-        if (element)
-            return promise.resolve(element);
-        setTimeout(resolveIfReady, 50);
-    }
+BenchmarkRunner.prototype = {
+    _appendFrame: function()
+    {
+        var frame = document.createElement("iframe");
+        frame.setAttribute("scrolling", "no");
+
+        this._frameContainer.insertBefore(frame, this._frameContainer.firstChild);
+        this._frame = frame;
+        return frame;
+    },
+
+    _removeFrame: function()
+    {
+        if (this._frame) {
+            this._frame.parentNode.removeChild(this._frame);
+            this._frame = null;
+        }
+    },
+
+    _runBenchmarkAndRecordResults: function(state)
+    {
+        var promise = new SimplePromise;
+        var suite = state.currentSuite();
+        var test = state.currentTest();
 
-    resolveIfReady();
-    return promise;
-};
+        if (this._client && this._client.willRunTest)
+            this._client.willRunTest(suite, test);
 
-BenchmarkRunner.prototype._appendFrame = function()
-{
-    var frame = document.createElement("iframe");
-    frame.setAttribute("scrolling", "no");
+        var contentWindow = this._frame.contentWindow;
+        var self = this;
 
-    this._frameContainer.insertBefore(frame, this._frameContainer.firstChild);
-    this._frame = frame;
-    return frame;
-};
+        var options = { complexity: test.complexity };
+        Utilities.extendObject(options, this._client.options);
+        Utilities.extendObject(options, contentWindow.Utilities.parseParameters());
 
-BenchmarkRunner.prototype._removeFrame = function()
-{
-    if (this._frame) {
-        this._frame.parentNode.removeChild(this._frame);
-        this._frame = null;
-    }
-};
+        var benchmark = new contentWindow.benchmarkClass(options);
+        benchmark.run().then(function(sampler) {
+            var samplers = self._suitesSamplers[suite.name] || {};
+            samplers[test.name] = sampler.toJSON(true, true);
+            self._suitesSamplers[suite.name] = samplers;
 
-BenchmarkRunner.prototype._runTestAndRecordResults = function(state)
-{
-    var promise = new SimplePromise;
-    var suite = state.currentSuite();
-    var test = state.currentTest();
-    
-    if (this._client && this._client.willRunTest)
-        this._client.willRunTest(suite, test);
-
-    var contentWindow = this._frame.contentWindow;
-    var self = this;
-
-    suite.run(contentWindow, test, this._client.options, this._client.progressBar).then(function(sampler) {
-        var samplers = self._suitesSamplers[suite.name] || {};
-        samplers[test.name] = sampler.toJSON(true, true);
-        self._suitesSamplers[suite.name] = samplers;
-
-        if (self._client && self._client.didRunTest)
-            self._client.didRunTest(suite, test);
-        
-        state.next();
-        if (state.currentSuite() != suite)
-            self._removeFrame();
-        promise.resolve(state);
-    });
-    
-    return promise;
-};
+            if (self._client && self._client.didRunTest)
+                self._client.didRunTest(suite, test);
 
-BenchmarkRunner.prototype.step = function(state)
-{
-    if (!state) {
-        state = new BenchmarkRunnerState(this._suites);
-        this._suitesSamplers = {};
-    }
+            state.next();
+            if (state.currentSuite() != suite)
+                self._removeFrame();
+            promise.resolve(state);
+        });
 
-    var suite = state.currentSuite();
-    if (!suite) {
-        this._finalize();
-        var promise = new SimplePromise;
-        promise.resolve();
         return promise;
+    },
+
+    step: function(state)
+    {
+        if (!state) {
+            state = new BenchmarkRunnerState(this._suites);
+            this._suitesSamplers = {};
+        }
+
+        var suite = state.currentSuite();
+        if (!suite) {
+            this._finalize();
+            var promise = new SimplePromise;
+            promise.resolve();
+            return promise;
+        }
+
+        if (state.isFirstTest()) {
+            this._appendFrame();
+        }
+
+        return state.prepareCurrentTest(this, this._frame).then(function(prepareReturnValue) {
+            return this._runBenchmarkAndRecordResults(state);
+        }.bind(this));
+    },
+
+    runAllSteps: function(startingState)
+    {
+        var nextCallee = this.runAllSteps.bind(this);
+        this.step(startingState).then(function(nextState) {
+            if (nextState)
+                nextCallee(nextState);
+        });
+    },
+
+    runMultipleIterations: function()
+    {
+        var self = this;
+        var currentIteration = 0;
+
+        this._runNextIteration = function() {
+            currentIteration++;
+            if (currentIteration < self._client.iterationCount)
+                self.runAllSteps();
+            else if (this._client && this._client.didFinishLastIteration)
+                self._client.didFinishLastIteration();
+        }
+
+        if (this._client && this._client.willStartFirstIteration)
+            this._client.willStartFirstIteration();
+
+        this.runAllSteps();
+    },
+
+    _finalize: function()
+    {
+        this._removeFrame();
+
+        if (this._client && this._client.didRunSuites)
+            this._client.didRunSuites(this._suitesSamplers);
+
+        if (this._runNextIteration)
+            this._runNextIteration();
     }
-
-    if (state.isFirstTest()) {
-        this._appendFrame();
-    }
-
-    return state.prepareCurrentTest(this, this._frame).then(function(prepareReturnValue) {
-        return this._runTestAndRecordResults(state);
-    }.bind(this));
-};
-
-BenchmarkRunner.prototype.runAllSteps = function(startingState)
-{
-    var nextCallee = this.runAllSteps.bind(this);
-    this.step(startingState).then(function(nextState) {
-        if (nextState)
-            nextCallee(nextState);
-    });
-};
-
-BenchmarkRunner.prototype.runMultipleIterations = function()
-{
-    var self = this;
-    var currentIteration = 0;
-
-    this._runNextIteration = function() {
-        currentIteration++;
-        if (currentIteration < self._client.iterationCount)
-            self.runAllSteps();
-        else if (this._client && this._client.didFinishLastIteration)
-            self._client.didFinishLastIteration();
-    }
-
-    if (self._client && self._client.willStartFirstIteration)
-        self._client.willStartFirstIteration();
-
-    self.runAllSteps();
-};
-
-BenchmarkRunner.prototype._finalize = function()
-{
-    this._removeFrame();
-        
-    if (this._client && this._client.didRunSuites)
-        this._client.didRunSuites(this._suitesSamplers);
-
-    if (this._runNextIteration)
-        this._runNextIteration();
 };
index 082e8b7..f549710 100644 (file)
@@ -73,15 +73,15 @@ Utilities.extendObject(Headers, {
 
 Suites.push(new Suite("HTML suite",
     [
-        { 
+        {
             url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=12&particleHeight=12&shape=circle",
             name: "CSS bouncing circles"
         },
-        { 
+        {
             url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=40&particleHeight=40&shape=rect&clip=star",
             name: "CSS bouncing clipped rects"
         },
-        { 
+        {
             url: "bouncing-particles/bouncing-css-shapes.html?particleWidth=50&particleHeight=50&shape=circle&fill=gradient",
             name: "CSS bouncing gradient circles"
         },
@@ -106,19 +106,19 @@ Suites.push(new Suite("HTML suite",
 
 Suites.push(new Suite("Canvas suite",
     [
-        { 
+        {
             url: "bouncing-particles/bouncing-canvas-shapes.html?particleWidth=12&particleHeight=12&shape=circle",
             name: "canvas bouncing circles"
         },
-        { 
+        {
             url: "bouncing-particles/bouncing-canvas-shapes.html?particleWidth=40&particleHeight=40&shape=rect&clip=star",
             name: "canvas bouncing clipped rects"
         },
-        { 
+        {
             url: "bouncing-particles/bouncing-canvas-shapes.html?particleWidth=50&particleHeight=50&shape=circle&fill=gradient",
             name: "canvas bouncing gradient circles"
         },
-        { 
+        {
             url: "bouncing-particles/bouncing-canvas-images.html?particleWidth=80&particleHeight=80&imageSrc=../resources/yin-yang.svg",
             name: "canvas bouncing SVG images"
         },
@@ -246,12 +246,12 @@ Suites.push(new Suite("Miscellaneous Tests",
             name: "Composited Transforms"
         },
         {
-            url: "examples/canvas-electrons.html",
-            name: "canvas electrons"
+            url: "misc/canvas-electrons.html",
+            name: "Canvas electrons"
         },
         {
-            url: "examples/canvas-stars.html",
-            name: "canvas stars"
+            url: "misc/canvas-stars.html",
+            name: "Canvas stars"
         },
     ]
 ));
index 738ab44..84cc1fd 100644 (file)
@@ -76,34 +76,34 @@ Point.prototype =
     {
         return this.x;
     },
-    
+
     // Used when the point object is used as a size object.
     get height()
     {
         return this.y;
     },
-    
+
     // Used when the point object is used as a size object.
     get center()
     {
         return new Point(this.x / 2, this.y / 2);
     },
-    
+
     add: function(other)
     {
         return new Point(this.x + other.x, this.y + other.y);
     },
-    
+
     subtract: function(other)
     {
         return new Point(this.x - other.x, this.y - other.y);
     },
-    
+
     multiply: function(other)
     {
         return new Point(this.x * other.x, this.y * other.y);
     },
-    
+
     move: function(angle, velocity, timeDelta)
     {
         return this.add(Point.pointOnCircle(angle, velocity * (timeDelta / 1000)));
@@ -139,7 +139,7 @@ Insets.prototype =
     {
         return this.top + this.bottom;
     },
-    
+
     get size()
     {
         return new Point(this.width, this.height);
@@ -156,10 +156,10 @@ SimplePromise.prototype.then = function (callback)
 {
     if (this._callback)
         throw "SimplePromise doesn't support multiple calls to then";
-        
+
     this._callback = callback;
     this._chainedPromise = new SimplePromise;
-    
+
     if (this._resolved)
         this.resolve(this._resolvedValue);
 
@@ -201,13 +201,13 @@ window.DocumentExtension =
         const xlinkNamespace = "http://www.w3.org/1999/xlink";
 
         var element = document.createElementNS(svgNamespace, name);
-        
+
         for (var key in attrs)
             element.setAttribute(key, attrs[key]);
-            
+
         for (var key in xlinkAttrs)
             element.setAttributeNS(xlinkNamespace, key, xlinkAttrs[key]);
-            
+
         parentElement.appendChild(element);
         return element;
     }
@@ -215,26 +215,23 @@ window.DocumentExtension =
 
 function ProgressBar(element, ranges)
 {
-    this.element = element;
-    this.ranges = ranges;
-    this.currentRange = 0;
+    this._element = element;
+    this._ranges = ranges;
+    this._currentRange = 0;
+    this._updateElement();
 }
 
 ProgressBar.prototype =
 {
-    _progressToPercent: function(progress)
-    {
-        return progress * (100 / this.ranges);
-    },
-    
-    incRange: function()
+    _updateElement: function()
     {
-        ++this.currentRange;
+        this._element.style.width = (this._currentRange * (100 / this._ranges)) + "%";
     },
-    
-    setPos: function(progress)
+
+    incrementRange: function()
     {
-        this.element.style.width = this._progressToPercent(this.currentRange + progress) + "%";
+        ++this._currentRange;
+        this._updateElement();
     }
 }
 
@@ -248,25 +245,25 @@ ResultsDashboard.prototype =
 {
     push: function(suitesSamplers)
     {
-        this._iterationsSamplers.push(suitesSamplers);        
+        this._iterationsSamplers.push(suitesSamplers);
     },
-    
+
     _processData: function(statistics, graph)
     {
         var iterationsResults = [];
         var iterationsScores = [];
-        
+
         this._iterationsSamplers.forEach(function(iterationSamplers, index) {
             var suitesResults = {};
             var suitesScores = [];
-        
+
             for (var suiteName in iterationSamplers) {
                 var suite = suiteFromName(suiteName);
                 var suiteSamplerData = iterationSamplers[suiteName];
 
                 var testsResults = {};
                 var testsScores = [];
-                
+
                 for (var testName in suiteSamplerData) {
                     testsResults[testName] = suiteSamplerData[testName];
                     testsScores.push(testsResults[testName][Strings.json.score]);
@@ -277,7 +274,7 @@ ResultsDashboard.prototype =
                 suitesResults[suiteName][Strings.json.results.tests] = testsResults;
                 suitesScores.push(suitesResults[suiteName][Strings.json.score]);
             }
-            
+
             iterationsResults[index] = {};
             iterationsResults[index][Strings.json.score] = Statistics.geometricMean(suitesScores);
             iterationsResults[index][Strings.json.results.suites] = suitesResults;
@@ -345,7 +342,7 @@ ResultsTable.prototype =
         var data = testResults[Strings.json.samples];
         if (!data)
             return;
-        
+
         var button = DocumentExtension.createElement("button", { class: "small-button" }, td);
 
         button.addEventListener("click", function() {
@@ -365,7 +362,7 @@ ResultsTable.prototype =
                 complexity[Strings.json.measurements.concern].toFixed(2)].join("");
             benchmarkController.showTestGraph(testName, score, mean, axes, samples, samplingTimeOffset);
         });
-            
+
         button.textContent = Strings.text.results.graph + "...";
     },
 
@@ -373,10 +370,10 @@ ResultsTable.prototype =
     {
         const percentThreshold = 10;
         const averageThreshold = 2;
-         
+
         if (measurement == Strings.json.measurements.percent)
             return data[Strings.json.measurements.percent] >= percentThreshold;
-            
+
         if (jsonExperiment == Strings.json.experiments.frameRate && measurement == Strings.json.measurements.average)
             return Math.abs(data[Strings.json.measurements.average] - options["frame-rate"]) >= averageThreshold;
 
@@ -445,7 +442,7 @@ ResultsTable.prototype =
             this._addTest(testName, testResults, options);
         }
     },
-    
+
     _addIteration: function(iterationResult, options)
     {
         for (var suiteName in iterationResult[Strings.json.results.suites]) {
@@ -458,7 +455,7 @@ ResultsTable.prototype =
     {
         this.clear();
         this._addHeader();
-        
+
         iterationsResults.forEach(function(iterationResult) {
             this._addIteration(iterationResult, options);
         }, this);
@@ -506,5 +503,14 @@ window.Utilities =
     mergeObjects: function(obj1, obj2)
     {
         return this.extendObject(this.copyObject(obj1), obj2);
+    },
+
+    createSubclass: function(superclass, classConstructor, extend)
+    {
+        classConstructor.prototype = Object.create(superclass.prototype);
+        classConstructor.prototype.constructor = classConstructor;
+        if (extend)
+            Utilities.extendObject(classConstructor.prototype, extend);
+        return classConstructor;
     }
 }
index 0498135..e9d602d 100644 (file)
@@ -5,7 +5,6 @@ window.benchmarkRunnerClient = {
 
     initialize: function(suites, options)
     {
-        this.testsCount = this.iterationCount * suites.reduce(function (count, suite) { return count + suite.tests.length; }, 0);
         this.options = options;
     },
 
index f984181..ff08faa 100644 (file)
@@ -7,16 +7,6 @@ var Suite = function(name, tests) {
     this.name = name;
     this.tests = tests;
 };
-Suite.prototype.prepare = function(runner, contentWindow, contentDocument)
-{
-    return runner.waitForElement("#stage").then(function (element) {
-        return element;
-    });
-};
-Suite.prototype.run = function(contentWindow, test, options, progressBar)
-{
-    return contentWindow.runBenchmark(this, test, options, progressBar);
-};
 
 var Suites = [];
 
index 8293cbe..81f46be 100644 (file)
@@ -4,24 +4,18 @@ var Strings = {
         score: "Score",
         samples: "Samples",
 
-        runningState: {
-            warming: "Warming",
-            sampling: "Sampling",
-            finished: "Finished"
-        },
-
         experiments: {
             complexity: "Complexity",
             frameRate: "FPS"
         },
-        
+
         measurements: {
             average: "Avg.",
             concern: "W.5%",
             stdev: "Std.",
             percent:  "%"
         },
-        
+
         results: {
             results: "Results",
             graph: "Graph",
@@ -31,25 +25,25 @@ var Strings = {
     json: {
         score: "score",
         samples: "samples",
-        
+
         experiments: {
             complexity: "complexity",
             frameRate: "frameRate"
         },
-        
+
         measurements: {
             average: "average",
             concern: "concern",
             stdev: "stdev",
             percent: "percent"
         },
-        
+
         results: {
             iterations: "iterationsResults",
             suites: "suitesResults",
             tests: "testsResults"
         },
-        
+
         graph: {
             points: "points",
             samplingTimeOffset: "samplingTimeOffset"
index ad806db..600485f 100644 (file)
@@ -1,27 +1,26 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
     <style>
         img.hidden {
             position: absolute;
             visibility: hidden;
         }
     </style>
-    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <img class="hidden" src="../resources/yin-yang.svg">
+    <img class="hidden" src="../resources/yin-yang.png">
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-canvas-particles.js"></script>
     <script src="resources/bouncing-canvas-images.js"></script>
-</head>
-<body>
-    <img class="hidden" src="../resources/yin-yang.svg">
-    <img class="hidden" src="../resources/yin-yang.png">
-    <canvas id="stage"></canvas>
 </body>
 </html>
index d1d7c06..170edf8 100644 (file)
@@ -2,18 +2,17 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-canvas-particles.js"></script>
     <script src="resources/bouncing-canvas-shapes.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
index 961bcfc..b3a7bda 100644 (file)
@@ -1,23 +1,22 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
     <style>
         img {
             position: absolute;
         }
     </style>
-    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <div id="stage"></div>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-css-images.js"></script>
-</head>
-<body>
-    <div id="stage"></div>
 </body>
 </html>
index 4eab1c2..39a428c 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
     <style>
         .circle {
             position: absolute;
         }
         .star {
             -webkit-clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
-            -ms-clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);  
+            -ms-clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
             clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
         }
     </style>
-    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <div id="stage"></div>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-css-shapes.js"></script>
-</head>
-<body>
-    <div id="stage"></div>
 </body>
 </html>
index 52dc155..23da735 100644 (file)
@@ -2,18 +2,17 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <svg id="stage"></svg>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-svg-particles.js"></script>
     <script src="resources/bouncing-svg-images.js"></script>
-</head>
-<body>
-    <svg id="stage"></svg>
 </body>
 </html>
index d579b71..7d32b4e 100644 (file)
@@ -2,18 +2,17 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <svg id="stage"></svg>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/bouncing-particles.js"></script>
     <script src="resources/bouncing-svg-particles.js"></script>
     <script src="resources/bouncing-svg-shapes.js"></script>
-</head>
-<body>
-    <svg id="stage"></svg>
 </body>
 </html>
index 28a7811..d1eb111 100644 (file)
@@ -1,51 +1,47 @@
-function BouncingCanvasImage(stage)
-{
-    BouncingCanvasParticle.call(this, stage);
-    this._imageElement = stage.imageElement;
-    this._shape = "image";
-}
-
-BouncingCanvasImage.prototype = Object.create(BouncingCanvasParticle.prototype);
-BouncingCanvasImage.prototype.constructor = BouncingCanvasImage;
-
-BouncingCanvasImage.prototype._draw = function()
-{
-    this._context.save();
-        this._applyRotation();
-        this._context.drawImage(this._imageElement, 0, 0, this._size.x, this._size.y);
-    this._context.restore();
-}
-
-function BouncingCanvasImagesStage(element, options)
-{
-    BouncingCanvasParticlesStage.call(this, element, options);
-
-    var imageSrc = options["imageSrc"] || "resources/yin-yang.svg";
-    this.imageElement = document.querySelector(".hidden[src=\"" + imageSrc + "\"]");
-}
-
-BouncingCanvasImagesStage.prototype = Object.create(BouncingCanvasParticlesStage.prototype);
-BouncingCanvasImagesStage.prototype.constructor = BouncingCanvasImagesStage;
-
-BouncingCanvasImagesStage.prototype.createParticle = function()
-{
-    return new BouncingCanvasImage(this);
-}
-
-function BouncingCanvasImagesBenchmark(suite, test, options, progressBar)
-{
-    BouncingCanvasParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
-
-BouncingCanvasImagesBenchmark.prototype = Object.create(BouncingCanvasParticlesBenchmark.prototype);
-BouncingCanvasImagesBenchmark.prototype.constructor = BouncingCanvasImagesBenchmark;
-
-BouncingCanvasImagesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingCanvasImagesStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingCanvasImagesBenchmark(suite, test, options, progressBar);
-}
+(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)
+    {
+        BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark);
+        var imageSrc = benchmark.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;
+
+})();
index 0b40da2..9b18944 100644 (file)
@@ -1,10 +1,55 @@
-function BouncingCanvasParticle(stage)
-{
-    BouncingParticle.call(this, stage);
-    this._context = stage.context;
-    this._shape = "";
-    this._clip = stage.clip;
-}
+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: [
@@ -18,88 +63,26 @@ BouncingCanvasParticle.clips = {
         new Point(0.70, 0.60),
         new Point(1.00, 0.38),
         new Point(0.62, 0.38)
-    ],
+    ]
 };
 
-BouncingCanvasParticle.prototype = Object.create(BouncingParticle.prototype);
-BouncingCanvasParticle.prototype.constructor = BouncingCanvasParticle;
-
-BouncingCanvasParticle.prototype._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);
-}
-
-BouncingCanvasParticle.prototype._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();
-}
-
-BouncingCanvasParticle.prototype._draw = function()
-{
-    throw "Not implemented";
-}
-
-BouncingCanvasParticle.prototype.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();
-}
-
-function BouncingCanvasParticlesStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this.context = this.element.getContext("2d");
-}
-
-BouncingCanvasParticlesStage.prototype = Object.create(BouncingParticlesStage.prototype);
-BouncingCanvasParticlesStage.prototype.constructor = BouncingCanvasParticlesStage;
-
-function BouncingCanvasParticlesAnimator(benchmark, options)
-{
-    BouncingParticlesAnimator.call(this, benchmark, options);
-    this._context = benchmark._stage.context;
-}
-
-BouncingCanvasParticlesAnimator.prototype = Object.create(BouncingParticlesAnimator.prototype);
-BouncingCanvasParticlesAnimator.prototype.constructor = BouncingCanvasParticlesAnimator;
-
-BouncingCanvasParticlesAnimator.prototype.animate = function()
-{
-    this._context.clearRect(0, 0, this._benchmark._stage.size.x, this._benchmark._stage.size.y);
-    return BouncingParticlesAnimator.prototype.animate.call(this);
-}
-
-function BouncingCanvasParticlesBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-BouncingCanvasParticlesBenchmark.prototype = Object.create(StageBenchmark.prototype);
-BouncingCanvasParticlesBenchmark.prototype.constructor = BouncingCanvasParticlesBenchmark;
-
-BouncingCanvasParticlesBenchmark.prototype.createAnimator = function()
-{
-    return new BouncingCanvasParticlesAnimator(this, this._options);
-}
\ No newline at end of file
+BouncingCanvasParticlesStage = Utilities.createSubclass(BouncingParticlesStage,
+    function()
+    {
+        BouncingParticlesStage.call(this);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        BouncingParticlesStage.prototype.initialize.call(this, benchmark);
+        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);
+        });
+    }
+});
index be4a1d9..13b1727 100644 (file)
@@ -1,90 +1,87 @@
-function BouncingCanvasShape(stage)
-{
-    BouncingCanvasParticle.call(this, stage);
-    this._fill = stage.fill;
-    this._shape = stage.shape;
-    this._color0 = stage.randomColor();
-    this._color1 = stage.randomColor();    
-}
+(function() {
 
-BouncingCanvasShape.prototype = Object.create(BouncingCanvasParticle.prototype);
-BouncingCanvasShape.prototype.constructor = BouncingCanvasShape;
+BouncingCanvasShape = Utilities.createSubclass(BouncingCanvasParticle,
+    function(stage)
+    {
+        BouncingCanvasParticle.call(this, stage, stage.shape);
+        this._fill = stage.fill;
+        this._color0 = stage.randomColor();
+        this._color1 = stage.randomColor();
+    }, {
 
-BouncingCanvasShape.prototype._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;
-    }
-}
+    _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;
 
-BouncingCanvasShape.prototype._drawShape = function()
-{
-    this._context.beginPath();
+        case "solid":
+        default:
+            this.context.fillStyle = this._color0;
+            break;
+        }
+    },
 
-    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;
-    }
+    _drawShape: function()
+    {
+        this.context.beginPath();
+
+        switch (this._shape) {
+        case "rect":
+            this.context.rect(0, 0, this.size.width, this.size.height);
+            break;
 
-    this._context.fill();
-}
+        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;
+        }
 
-BouncingCanvasShape.prototype._draw = function()
-{
-    this._context.save();
-        this._applyFill();
-        this._applyRotation();
-        this._applyClipping();
-        this._drawShape();
-    this._context.restore();
-}
+        this.context.fill();
+    },
 
-function BouncingCanvasShapesStage(element, options)
-{
-    BouncingCanvasParticlesStage.call(this, element, options);
-    this.parseShapeParamters(options);
-}
+    _draw: function()
+    {
+        this.context.save();
+            this._applyFill();
+            this.applyRotation();
+            this.applyClipping();
+            this._drawShape();
+        this.context.restore();
+    }
+});
 
-BouncingCanvasShapesStage.prototype = Object.create(BouncingCanvasParticlesStage.prototype);
-BouncingCanvasShapesStage.prototype.constructor = BouncingCanvasShapesStage;
+BouncingCanvasShapesStage = Utilities.createSubclass(BouncingCanvasParticlesStage,
+    function ()
+    {
+        BouncingCanvasParticlesStage.call(this);
+    }, {
 
-BouncingCanvasShapesStage.prototype.createParticle = function()
-{
-    return new BouncingCanvasShape(this);
-}
+    initialize: function(benchmark)
+    {
+        BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark);
+        this.parseShapeParameters(benchmark.options);
+    },
 
-function BouncingCanvasShapesBenchmark(suite, test, options, progressBar)
-{
-    BouncingCanvasParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
+    createParticle: function()
+    {
+        return new BouncingCanvasShape(this);
+    }
+});
 
-BouncingCanvasShapesBenchmark.prototype = Object.create(BouncingCanvasParticlesBenchmark.prototype);
-BouncingCanvasShapesBenchmark.prototype.constructor = BouncingCanvasShapesBenchmark;
+BouncingCanvasShapesBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new BouncingCanvasShapesStage(), options);
+    }
+);
 
-BouncingCanvasShapesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingCanvasShapesStage(element, this._options);
-}
+window.benchmarkClass = BouncingCanvasShapesBenchmark;
 
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingCanvasShapesBenchmark(suite, test, options, progressBar);
-}
+})();
\ No newline at end of file
index 0d3ae24..4d006c3 100644 (file)
@@ -1,63 +1,61 @@
-function BouncingCssImage(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();
-}
-
-BouncingCssImage.prototype = Object.create(BouncingParticle.prototype);
-BouncingCssImage.prototype.constructor = BouncingCssImage;
-
-BouncingCssImage.prototype._move = function()
-{
-    this.element.style.transform = "translate(" + this._position.x + "px," + this._position.y + "px) " + this._rotater.rotateZ();
-}
-    
-BouncingCssImage.prototype.animate = function(timeDelta)
-{
-    BouncingParticle.prototype.animate.call(this, timeDelta);
-    this._move();
-}
-
-function BouncingCssImagesStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg";
-}
-
-BouncingCssImagesStage.prototype = Object.create(BouncingParticlesStage.prototype);
-BouncingCssImagesStage.prototype.constructor = BouncingCssImagesStage;
-
-BouncingCssImagesStage.prototype.createParticle = function()
-{
-    return new BouncingCssImage(this);
-}
-
-BouncingCssImagesStage.prototype.particleWillBeRemoved = function(particle)
-{
-    particle.element.remove();
-}
-
-function BouncingCssImagesBenchmark(suite, test, options, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
-
-BouncingCssImagesBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-BouncingCssImagesBenchmark.prototype.constructor = BouncingCssImagesBenchmark;
-
-BouncingCssImagesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingCssImagesStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingCssImagesBenchmark(suite, test, options, progressBar);
-}
+(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)
+    {
+        BouncingParticlesStage.prototype.initialize.call(this, benchmark);
+        this.imageSrc = benchmark.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;
+
+})();
index 6f94335..141e282 100644 (file)
@@ -1,81 +1,79 @@
-function BouncingCssShape(stage)
-{
-    BouncingParticle.call(this, stage);
+(function() {
 
-    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;
-    }
+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;
 
-    this._move();
-}
+        case "gradient":
+            this.element.style.background = "linear-gradient(" + stage.randomColor() + ", " + stage.randomColor() + ")";
+            break;
+        }
 
-BouncingCssShape.prototype = Object.create(BouncingParticle.prototype);
-BouncingCssShape.prototype.constructor = BouncingCssShape;
+        this._move();
+    }, {
 
-BouncingCssShape.prototype._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;
-}
+    _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;
+    },
 
-BouncingCssShape.prototype._move = function()
-{
-    this.element.style.transform = "translate(" + this._position.x + "px," + this._position.y + "px)" + this._rotater.rotateZ();
-}
-    
-BouncingCssShape.prototype.animate = function(timeDelta)
-{
-    BouncingParticle.prototype.animate.call(this, timeDelta);
-    this._rotater.next(timeDelta);
-    this._move();
-}
+    _move: function()
+    {
+        this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px)" + this.rotater.rotateZ();
+    },
 
-function BouncingCssShapesStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this.parseShapeParamters(options);
-}
+    animate: function(timeDelta)
+    {
+        BouncingParticle.prototype.animate.call(this, timeDelta);
+        this.rotater.next(timeDelta);
+        this._move();
+    }
+});
 
-BouncingCssShapesStage.prototype = Object.create(BouncingParticlesStage.prototype);
-BouncingCssShapesStage.prototype.constructor = BouncingCssShapesStage;
+BouncingCssShapesStage = Utilities.createSubclass(BouncingParticlesStage,
+    function()
+    {
+        BouncingParticlesStage.call(this);
+    }, {
 
-BouncingCssShapesStage.prototype.createParticle = function()
-{
-    return new BouncingCssShape(this);
-}
+    initialize: function(benchmark)
+    {
+        BouncingParticlesStage.prototype.initialize.call(this, benchmark);
+        this.parseShapeParameters(benchmark.options);
+    },
 
-BouncingCssShapesStage.prototype.particleWillBeRemoved = function(particle)
-{
-    particle.element.remove();
-}
+    createParticle: function()
+    {
+        return new BouncingCssShape(this);
+    },
 
-function BouncingCssShapesBenchmark(suite, test, options, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
+    particleWillBeRemoved: function(particle)
+    {
+        particle.element.remove();
+    }
+});
 
-BouncingCssShapesBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-BouncingCssShapesBenchmark.prototype.constructor = BouncingCssShapesBenchmark;
+BouncingCssShapesBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new BouncingCssShapesStage(), options);
+    }
+);
 
-BouncingCssShapesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingCssShapesStage(element, this._options);
-}
+window.benchmarkClass = BouncingCssShapesBenchmark;
 
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingCssShapesBenchmark(suite, test, options, progressBar);
-}
+})();
index a0f7bfd..50e65cc 100644 (file)
@@ -1,28 +1,28 @@
 function BouncingParticle(stage)
 {
     this._stageSize = stage.size;
-    this._size = stage.particleSize;
-    
-    this._position = stage.randomPosition(stage.size.subtract(stage.particleSize));
+    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();
+    this.rotater = stage.randomRotater();
 }
 
 BouncingParticle.prototype =
 {
     get center()
     {
-        return this._position.add(this._size.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);
+        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 (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;
@@ -30,11 +30,11 @@ BouncingParticle.prototype =
             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;
+            this.position.x = this._stageSize.x - this.size.x;
         }
-        
+
         // If particle is going to move off left side
-        if (this._position.x < 0) {
+        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;
@@ -42,97 +42,76 @@ BouncingParticle.prototype =
             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;
+            this.position.x = 0;
         }
 
         // If particle is going to move off bottom side
-        if (this._position.y + this._size.y > this._stageSize.y) {
+        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;
+            this.position.y = this._stageSize.y - this.size.y;
         }
 
         // If particle is going to move off top side
-        if (this._position.y < 0) {
+        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;
+            this.position.y = 0;
         }
     }
 }
 
-function BouncingParticlesAnimator(benchmark, options)
-{
-    StageAnimator.call(this, benchmark, options);
-};
-
-BouncingParticlesAnimator.prototype = Object.create(StageAnimator.prototype);
-BouncingParticlesAnimator.prototype.constructor = BouncingParticlesAnimator;
-
-function BouncingParticlesStage(element, options)
-{
-    Stage.call(this, element, options);
-    
-    this.particleSize = new Point(parseInt(options["particleWidth"]) || 10, parseInt(options["particleHeight"]) || 10);
-    this._particles = [];
-
-    this.maxVelocity = parseInt(options["maxVelocity"]) || 500;
-    this.maxVelocity = Math.max(this.maxVelocity, 100);
-}
+BouncingParticlesStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+        this.particles = [];
+    }, {
 
-BouncingParticlesStage.prototype = Object.create(Stage.prototype);
-BouncingParticlesStage.prototype.constructor = BouncingParticlesStage;
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this.particleSize = new Point(parseInt(benchmark.options["particleWidth"]) || 10, parseInt(benchmark.options["particleHeight"]) || 10);
+        this.maxVelocity = Math.max(parseInt(benchmark.options["maxVelocity"]) || 500, 100);
+    },
 
-BouncingParticlesStage.prototype.parseShapeParamters = function(options)
-{
-    this.shape = options["shape"] || "circle";
-    this.fill = options["fill"] || "solid";
-    this.clip = options["clip"] || "";
-}
+    parseShapeParameters: function(options)
+    {
+        this.shape = options["shape"] || "circle";
+        this.fill = options["fill"] || "solid";
+        this.clip = options["clip"] || "";
+    },
 
-BouncingParticlesStage.prototype.animate = function(timeDelta)
-{
-    this._particles.forEach(function(particle) {
-        particle.animate(timeDelta);
-    });
-}
-    
-BouncingParticlesStage.prototype.tune = function(count)
-{
-    if (count == 0)
-        return this._particles.length;
-
-    if (count > 0) {
-        console.assert(typeof(this.createParticle) == "function");
-        for (var i = 0; i < count; ++i)
-            this._particles.push(this.createParticle());
-        return this._particles.length;
-    }
+    animate: function(timeDelta)
+    {
+        this.particles.forEach(function(particle) {
+            particle.animate(timeDelta);
+        });
+    },
 
-    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]);
-    }
+    tune: function(count)
+    {
+        if (count == 0)
+            return this.particles.length;
 
-    this._particles.splice(-count, count);
-    return this._particles.length;
-}
+        if (count > 0) {
+            for (var i = 0; i < count; ++i)
+                this.particles.push(this.createParticle());
+            return this.particles.length;
+        }
 
-function BouncingParticlesBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
+        count = Math.min(-count, this.particles.length);
 
-BouncingParticlesBenchmark.prototype = Object.create(StageBenchmark.prototype);
-BouncingParticlesBenchmark.prototype.constructor = BouncingParticlesBenchmark;
+        if (typeof(this.particleWillBeRemoved) == "function") {
+            for (var i = 0; i < count; ++i)
+                this.particleWillBeRemoved(this.particles[this.particles.length - 1 - i]);
+        }
 
-BouncingParticlesBenchmark.prototype.createAnimator = function()
-{
-    return new BouncingParticlesAnimator(this, this._options);
-}
\ No newline at end of file
+        this.particles.splice(-count, count);
+        return this.particles.length;
+    }
+});
index 435f2ce..e331cc4 100644 (file)
@@ -1,45 +1,43 @@
-function BouncingSvgImage(stage)
-{
-    BouncingSvgParticle.call(this, stage);
-    this._shape = "image";
-    
-    var attrs = { x: 0, y: 0, width: this._size.x, height: this._size.y };
-    var xlinkAttrs = { href: stage.imageSrc };
-    this.element = DocumentExtension.createSvgElement("image", attrs, xlinkAttrs, stage.element);
-    this._move();
-}
-
-BouncingSvgImage.prototype = Object.create(BouncingSvgParticle.prototype);
-BouncingSvgImage.prototype.constructor = BouncingSvgImage;
-
-function BouncingSvgImagesStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this.imageSrc = options["imageSrc"] || "resources/yin-yang.svg";
-}
-
-BouncingSvgImagesStage.prototype = Object.create(BouncingSvgParticlesStage.prototype);
-BouncingSvgImagesStage.prototype.constructor = BouncingSvgImagesStage;
-
-BouncingSvgImagesStage.prototype.createParticle = function()
-{
-    return new BouncingSvgImage(this);
-}
-
-function BouncingSvgImagesBenchmark(suite, test, options, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
-
-BouncingSvgImagesBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-BouncingSvgImagesBenchmark.prototype.constructor = BouncingSvgImagesBenchmark;
-
-BouncingSvgImagesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingSvgImagesStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingSvgImagesBenchmark(suite, test, options, progressBar);
-}
+(function() {
+
+BouncingSvgImage = Utilities.createSubclass(BouncingSvgParticle,
+    function(stage)
+    {
+        BouncingSvgParticle.call(this, stage, "image");
+
+        var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y };
+        var xlinkAttrs = { href: stage.imageSrc };
+        this.element = DocumentExtension.createSvgElement("image", attrs, xlinkAttrs, stage.element);
+        this._move();
+    }
+);
+
+BouncingSvgImagesStage = Utilities.createSubclass(BouncingSvgParticlesStage,
+    function()
+    {
+        BouncingSvgParticlesStage.call(this);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark);
+        this.imageSrc = benchmark.options["imageSrc"] || "resources/yin-yang.svg";
+    },
+
+    createParticle: function()
+    {
+        return new BouncingSvgImage(this);
+    }
+});
+
+BouncingSvgImagesBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new BouncingSvgImagesStage(), options);
+    }
+);
+
+window.benchmarkClass = BouncingSvgImagesBenchmark;
+
+})();
+
index 69c6754..e39f2f0 100644 (file)
@@ -1,68 +1,67 @@
-function BouncingSvgParticle(stage)
-{
-    BouncingParticle.call(this, stage);
-}
+BouncingSvgParticle = Utilities.createSubclass(BouncingParticle,
+    function(stage, shape)
+    {
+        BouncingParticle.call(this, stage);
+        this._shape = shape;
+    }, {
 
-BouncingSvgParticle.prototype = Object.create(BouncingParticle.prototype);
-BouncingSvgParticle.prototype.constructor = BouncingParticle;
+    _applyClipping: function(stage)
+    {
+        if (stage.clip != "star")
+            return;
 
-BouncingSvgParticle.prototype._applyClipping = function(stage)
-{
-    if (stage.clip != "star")
-        return;
-        
-    stage.ensureClipStarIsCreated();
-    this.element.setAttribute("clip-path", "url(#star-clip)");
-}
+        stage.ensureClipStarIsCreated();
+        this.element.setAttribute("clip-path", "url(#star-clip)");
+    },
 
-BouncingSvgParticle.prototype._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);
-}
+    _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);
+    },
 
-BouncingSvgParticle.prototype.animate = function(timeDelta)
-{
-    BouncingParticle.prototype.animate.call(this, timeDelta);
-    this._move();
-}
+    animate: function(timeDelta)
+    {
+        BouncingParticle.prototype.animate.call(this, timeDelta);
+        this._move();
+    }
+});
 
-function BouncingSvgParticlesStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-}
+BouncingSvgParticlesStage = Utilities.createSubclass(BouncingParticlesStage,
+    function()
+    {
+        BouncingParticlesStage.call(this);
+    }, {
 
-BouncingSvgParticlesStage.prototype = Object.create(BouncingParticlesStage.prototype);
-BouncingSvgParticlesStage.prototype.constructor = BouncingSvgParticlesStage;
+    _createDefs: function()
+    {
+        return DocumentExtension.createSvgElement("defs", {}, {}, this.element);
+    },
 
-BouncingSvgParticlesStage.prototype._createDefs = function()
-{
-    return DocumentExtension.createSvgElement("defs", {}, {}, this.element);
-}
-                                                               
-BouncingSvgParticlesStage.prototype._ensureDefsIsCreated = function()
-{
-    return this.element.querySelector("defs") || this._createDefs();
-}
+    _ensureDefsIsCreated: function()
+    {
+        return this.element.querySelector("defs") || this._createDefs();
+    },
 
-BouncingSvgParticlesStage.prototype._createClipStar = function()
-{
-    var attrs = { id: "star-clip", clipPathUnits: "objectBoundingBox" };
-    var clipPath  = DocumentExtension.createSvgElement("clipPath", attrs, {}, this._ensureDefsIsCreated());
+    _createClipStar: function()
+    {
+        var attrs = { id: "star-clip", clipPathUnits: "objectBoundingBox" };
+        var clipPath  = DocumentExtension.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" };
-    DocumentExtension.createSvgElement("path", attrs, {}, clipPath);
-    return clipPath;
-}
+        attrs = { d: "M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" };
+        DocumentExtension.createSvgElement("path", attrs, {}, clipPath);
+        return clipPath;
+    },
 
-BouncingSvgParticlesStage.prototype.ensureClipStarIsCreated = function()
-{
-    return this.element.querySelector("#star-clip") || this._createClipStar();
-}
+    ensureClipStarIsCreated: function()
+    {
+        return this.element.querySelector("#star-clip") || this._createClipStar();
+    },
 
-BouncingSvgParticlesStage.prototype.particleWillBeRemoved = function(particle)
-{
-    particle.element.remove();
-}
+    particleWillBeRemoved: function(particle)
+    {
+        particle.element.remove();
+    }
+});
index d02801a..88cebaa 100644 (file)
-function BouncingSvgShape(stage)
-{
-    BouncingSvgParticle.call(this, stage);
-    this._shape = stage.shape;
-    this._fill = stage.fill;
-    
-    this._createShape(stage);
-    this._applyClipping(stage);
-    this._applyFill(stage);
-
-    this._move();    
-}
-
-BouncingSvgShape.prototype = Object.create(BouncingSvgParticle.prototype);
-BouncingSvgShape.prototype.constructor = BouncingSvgShape;
-
-BouncingSvgShape.prototype._createShape = function(stage)
-{
-    switch (this._shape) {
-    case "rect":
-        var attrs = { x: 0, y: 0, width: this._size.x, height: this._size.y };
-        this.element = DocumentExtension.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 = DocumentExtension.createSvgElement("circle", attrs, {}, stage.element);
-        break;        
+(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 = DocumentExtension.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 = DocumentExtension.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;
+        }
     }
-}
-
-BouncingSvgShape.prototype._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)
+    {
+        BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark);
+        this.parseShapeParameters(benchmark.options);
+        this._gradientsCount = 0;
+    },
+
+    createGradient: function(stops)
+    {
+        var attrs = { id: "gradient-" + ++this._gradientsCount };
+        var gradient = DocumentExtension.createSvgElement("linearGradient", attrs, {}, this._ensureDefsIsCreated());
+
+        for (var i = 0; i < stops; ++i) {
+            attrs = { offset: i * 100 / stops + "%", 'stop-color': this.randomColor() };
+            DocumentExtension.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);
     }
-}
-
-function BouncingSvgShapesStage(element, options)
-{
-    BouncingSvgParticlesStage.call(this, element, options);
-    this.parseShapeParamters(options);
-    this._gradientsCount = 0;
-}
-
-BouncingSvgShapesStage.prototype = Object.create(BouncingSvgParticlesStage.prototype);
-BouncingSvgShapesStage.prototype.constructor = BouncingSvgShapesStage;
-                                                               
-BouncingSvgShapesStage.prototype.createGradient = function(stops)
-{
-    var attrs = { id: "gadient-" + ++this._gradientsCount };
-    var gradient = DocumentExtension.createSvgElement("linearGradient", attrs, {}, this._ensureDefsIsCreated());    
-    
-    for (var i = 0; i < stops; ++i) {
-        attrs = { offset: i * 100 / stops + "%", 'stop-color': this.randomColor() };
-        DocumentExtension.createSvgElement("stop", attrs, {}, gradient);
+});
+
+BouncingSvgShapesBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new BouncingSvgShapesStage(), options);
     }
+);
+
+window.benchmarkClass = BouncingSvgShapesBenchmark;
 
-    return gradient;
-}
-
-BouncingSvgShapesStage.prototype.createParticle = function()
-{
-    return new BouncingSvgShape(this);
-}
-
-BouncingSvgShapesStage.prototype.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);
-}
-
-function BouncingSvgShapesBenchmark(suite, test, options, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
-
-BouncingSvgShapesBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-BouncingSvgShapesBenchmark.prototype.constructor = BouncingSvgShapesBenchmark;
-
-BouncingSvgShapesBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingSvgShapesStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new BouncingSvgShapesBenchmark(suite, test, options, progressBar);
-}
+})();
diff --git a/PerformanceTests/Animometer/tests/examples/resources/canvas-electrons.js b/PerformanceTests/Animometer/tests/examples/resources/canvas-electrons.js
deleted file mode 100644 (file)
index 8de5840..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-function CanvasElectron(stage)
-{
-    this._context = stage.context;
-    this._stageSize = stage.size;
-
-    var minSide = Math.min(this._stageSize.width, this._stageSize.height);
-    var radiusX = stage.random(minSide / 8, 7 * minSide / 16);
-    var radiusY = stage.random(minSide / 8, 3 * radiusX / 4);
-    this._orbitRadiuses = new Point(radiusX, radiusY);
-    this._radius = stage.random(5, 15);
-    this._direction = stage.randomInt(0, 2);
-    this._angle = stage.randomInt(0, 360);
-    this._color = stage.randomColor();
-    this._rotater = stage.randomRotater();
-    this._rotater.next(stage.random(0, this._rotater.interval));
-}
-
-CanvasElectron.prototype._draw = function()
-{
-    // Calculate the position of the object on the ellipse.
-    var angle = this._direction ? this._rotater.degree() : 360 - this._rotater.degree();
-    var position = this._stageSize.center.subtract(Point.pointOnEllipse(angle, this._orbitRadiuses));
-
-    this._context.save();    
-        this._context.translate(this._stageSize.center.x, this._stageSize.center.y);
-        this._context.rotate(this._angle * Math.PI / 180);
-        this._context.translate(-this._stageSize.center.x, -this._stageSize.center.y);
-
-        // Set the stroke and the fill colors
-        this._context.strokeStyle = "rgba(192, 192, 192, 0.9)";
-        this._context.fillStyle = this._color;
-
-        // Draw the orbit of the object.
-        this._context.beginPath();
-        this._context.ellipse(this._stageSize.center.x, this._stageSize.center.y, this._orbitRadiuses.x, this._orbitRadiuses.y, 0, 0, 2 * Math.PI);
-        this._context.stroke();
-    
-        // Draw the object.
-        this._context.beginPath();
-        this._context.arc(position.x, position.y, this._radius, 0, Math.PI * 2, true);
-        this._context.fill();
-    this._context.restore();
-}
-
-CanvasElectron.prototype.animate = function(timeDelta)
-{
-    this._rotater.next(timeDelta / 100);
-    this._draw();
-}
-
-function CanvasElectronsStage(element, options)
-{
-    Stage.call(this, element, options);
-    this.context = this.element.getContext("2d");
-    this._electrons = [];
-}
-
-CanvasElectronsStage.prototype = Object.create(Stage.prototype);
-CanvasElectronsStage.prototype.constructor = CanvasElectronsStage;
-
-CanvasElectronsStage.prototype.tune = function(count)
-{
-    if (count == 0)
-        return this._electrons.length;
-
-    if (count > 0) {
-        for (var i = 0; i < count; ++i)
-            this._electrons.push(new CanvasElectron(this));
-        return this._electrons.length;
-    }
-
-    count = Math.min(-count, this._electrons.length);
-    this._electrons.splice(-count, count);
-    
-    return this._electrons.length;
-}
-
-CanvasElectronsStage.prototype.animate = function(timeDelta)
-{
-    this._electrons.forEach(function(electron) {
-        electron.animate(timeDelta);
-    });
-}
-
-function CanvasElectronsAnimator(benchmark, options)
-{
-    Animator.call(this, benchmark, options);
-    this._context = benchmark._stage.context;
-}
-
-CanvasElectronsAnimator.prototype = Object.create(StageAnimator.prototype);
-CanvasElectronsAnimator.prototype.constructor = CanvasElectronsAnimator;
-
-CanvasElectronsAnimator.prototype.animate = function()
-{
-    this._context.clearRect(0, 0, this._benchmark._stage.size.x, this._benchmark._stage.size.y);
-
-    // Draw a big star in the middle.
-    this._context.fillStyle = "orange";    
-    this._context.beginPath();
-    this._context.arc(this._benchmark._stage.size.center.x, this._benchmark._stage.size.center.y, 50, 0, Math.PI * 2, true);
-    this._context.fill();
-
-    return StageAnimator.prototype.animate.call(this);
-}
-
-function CanvasElectronsBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-CanvasElectronsBenchmark.prototype = Object.create(StageBenchmark.prototype);
-CanvasElectronsBenchmark.prototype.constructor = CanvasElectronsBenchmark;
-
-CanvasElectronsBenchmark.prototype.createStage = function(element)
-{
-    // Attach the stage to the benchmark.
-    return new CanvasElectronsStage(element, this._options);
-}
-
-CanvasElectronsBenchmark.prototype.createAnimator = function()
-{
-    // Attach the animator to the benchmark.
-    return new CanvasElectronsAnimator(this, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    // This function is called from the test harness which starts the
-    // test by creating your benchmark object.
-    return new CanvasElectronsBenchmark(suite, test, options, progressBar);
-}
diff --git a/PerformanceTests/Animometer/tests/examples/resources/canvas-stars.js b/PerformanceTests/Animometer/tests/examples/resources/canvas-stars.js
deleted file mode 100644 (file)
index d37c2a2..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-function CanvasStar(stage)
-{
-    this._context = stage.context;
-    this._stageSize = stage.size;
-
-    this._size = stage.randomSquareSize(5, 20);
-    this._center = stage.randomPosition(stage.size.subtract(this._size)).add(this._size.center);
-    this._rotateX = 0;
-    this._rotateDeltaX = stage.random(0.3, 0.7);
-}
-
-CanvasStar.prototype._draw = function()
-{
-    this._context.save();
-    this._context.translate(this._center.x, this._center.y);
-    
-    this._context.fillStyle = 'yellow';
-    this._context.strokeStyle = 'white';
-
-    this._context.lineWidth = 1;
-    
-    this._context.beginPath();
-    this._context.moveTo(                                     0, -this._size.y /  2);
-    this._context.lineTo(+this._size.x / 20 - this._rotateX / 5, -this._size.y / 10);
-    this._context.lineTo(+this._size.x / 4  - this._rotateX,                      0);
-    this._context.lineTo(+this._size.x / 20 - this._rotateX / 5, +this._size.y / 10);
-    this._context.lineTo(                                     0, +this._size.y /  2);
-    this._context.lineTo(-this._size.x / 20 + this._rotateX / 5, +this._size.y / 10);
-    this._context.lineTo(-this._size.x /  4 + this._rotateX,                      0);
-    this._context.lineTo(-this._size.x / 20 + this._rotateX / 5, -this._size.y / 10);
-    this._context.lineTo(                                     0, -this._size.y /  2);
-    
-    this._context.fill();
-    this._context.stroke();
-    this._context.closePath();
-    this._context.restore();
-}
-
-CanvasStar.prototype.animate = function(timeDelta)
-{
-    this._rotateX += this._rotateDeltaX;
-    
-    if (this._rotateX > this._size.x / 4 || this._rotateX < -this._size.x / 4) {
-        this._rotateDeltaX = -this._rotateDeltaX;
-        this._rotateX += this._rotateDeltaX;
-    }
-
-   this._draw();
-}
-
-function CanvasStarsStage(element, options)
-{
-   Stage.call(this, element, options);
-   this.context = this.element.getContext("2d");
-
-    this._objects = [];
-}
-
-CanvasStarsStage.prototype = Object.create(Stage.prototype);
-CanvasStarsStage.prototype.constructor = CanvasStarsStage;
-
-CanvasStarsStage.prototype.tune = function(count)
-{
-    if (count == 0)
-        return this._objects.length;
-
-    if (count > 0) {
-        for (var i = 0; i < count; ++i)
-            this._objects.push(new CanvasStar(this));
-        return this._objects.length;
-    }
-
-    count = Math.min(-count, this._objects.length);
-    this._objects.splice(-count, count);
-
-    return this._objects.length;
-}
-
-CanvasStarsStage.prototype.animate = function(timeDelta)
-{
-    this._objects.forEach(function(object) {
-        object.animate(timeDelta);
-    });
-}
-
-function CanvasStarsAnimator(benchmark, options)
-{
-   Animator.call(this, benchmark, options);
-   this._context = benchmark._stage.context;
-}
-
-CanvasStarsAnimator.prototype = Object.create(StageAnimator.prototype);
-CanvasStarsAnimator.prototype.constructor = CanvasStarsAnimator;
-
-CanvasStarsAnimator.prototype.animate = function()
-{
-    this._context.beginPath();
-    this._context.fillStyle = 'black';
-    this._context.rect(0, 0, this._benchmark._stage.size.width, this._benchmark._stage.size.height);
-    this._context.fill();
-   return StageAnimator.prototype.animate.call(this);
-}
-
-function CanvasStarsBenchmark(suite, test, options, progressBar)
-{
-   StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-CanvasStarsBenchmark.prototype = Object.create(StageBenchmark.prototype);
-CanvasStarsBenchmark.prototype.constructor = CanvasStarsBenchmark;
-
-CanvasStarsBenchmark.prototype.createStage = function(element)
-{
-   // Attach the stage to the benchmark.
-   return new CanvasStarsStage(element, this._options);
-}
-
-CanvasStarsBenchmark.prototype.createAnimator = function()
-{
-   // Attach the animator to the benchmark.
-   return new CanvasStarsAnimator(this, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-   // This function is called from the test harness which starts the
-   // test by creating your benchmark object.
-   return new CanvasStarsBenchmark(suite, test, options, progressBar);
-}
\ No newline at end of file
index 3f46ae9..cd06346 100644 (file)
@@ -2,17 +2,16 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/canvas-stage.js"></script>
     <script src="resources/canvas-tests.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
index cee8fca..53db13c 100644 (file)
@@ -1,61 +1,44 @@
-function SimpleCanvasStage(element, options, canvasObject)
-{
-    Stage.call(this, element, options);
-    this.options = options;
-    this.context = this.element.getContext("2d");
-    this.canvasObject = canvasObject;
-    this._objects = [];
-}
-SimpleCanvasStage.prototype = Object.create(Stage.prototype);
-SimpleCanvasStage.prototype.constructor = SimpleCanvasStage;
-SimpleCanvasStage.prototype.tune = function(count)
-{
-    if (count == 0)
-        return this._objects.length;
+SimpleCanvasStage = Utilities.createSubclass(Stage,
+    function(canvasObject)
+    {
+        Stage.call(this);
+        this._canvasObject = canvasObject;
+        this.objects = [];
+    }, {
 
-    if (count > 0) {
-        // For path-based tests, use the object length as a maximum coordinate value
-        // to make it easier to see what the test is doing
-        var coordinateMaximum = Math.max(this._objects.length, 200);
-        for (var i = 0; i < count; ++i) {
-            this._objects.push(new this.canvasObject(this, coordinateMaximum));
-        }
-        return this._objects.length;
-    }
-
-    count = Math.min(-count, this._objects.length);
-    this._objects.splice(0, count);
-    return this._objects.length;
-}
-SimpleCanvasStage.prototype.animate = function()
-{
-    var context = this.context;
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-}
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this.context = this.element.getContext("2d");
+    },
 
-function SimpleCanvasAnimator(benchmark, options)
-{
-    StageAnimator.call(this, benchmark, options);
-    this._context = benchmark._stage.context;
-}
+    tune: function(count)
+    {
+        if (count == 0)
+            return this.objects.length;
 
-SimpleCanvasAnimator.prototype = Object.create(StageAnimator.prototype);
-SimpleCanvasAnimator.prototype.constructor = SimpleCanvasAnimator;
-SimpleCanvasAnimator.prototype.animate = function()
-{
-    this._context.clearRect(0, 0, this._benchmark._stage.size.x, this._benchmark._stage.size.y);
-    return StageAnimator.prototype.animate.call(this, this._options);
-}
+        if (count > 0) {
+            for (var i = 0; i < count; ++i)
+                this.objects.push(new this._canvasObject(this));
+            return this.objects.length;
+        }
 
+        count = Math.min(-count, this.objects.length);
+        this.objects.splice(0, count);
+        return this.objects.length;
+    },
 
-function SimpleCanvasBenchmark(suite, test, options, progressBar) {
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-SimpleCanvasBenchmark.prototype = Object.create(StageBenchmark.prototype);
-SimpleCanvasBenchmark.prototype.constructor = SimpleCanvasBenchmark;
-SimpleCanvasBenchmark.prototype.createAnimator = function() {
-    return new SimpleCanvasAnimator(this, this._options);
-}
+    animate: function()
+    {
+        var context = this.context;
+        context.clearRect(0, 0, this.size.x, this.size.y);
+        this.objects.forEach(function(object) {
+            object.draw(context);
+        });
+    },
 
+    complexity: function()
+    {
+        return this.objects.length;
+    }
+});
index 564b58a..c3d74b1 100644 (file)
@@ -22,7 +22,7 @@ CanvasLineSegment.prototype.draw = function(context)
     context.strokeStyle = this._color;
     context.lineWidth = this._lineWidth;
 
-    this._length+=Math.sin(Date.now()/100*this._omega);
+    this._length += Math.sin(Date.now()/100*this._omega);
 
     context.beginPath();
     context.moveTo(this._startX, this._startY);
@@ -41,7 +41,7 @@ function CanvasArc(stage)
 
     this._point = new Point(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + .5));
 
-    this._radius = 20 + Math.pow(Math.random(), 5) * (Math.min(distanceX, distanceY) / 1.6);
+    this._radius = 20 + Math.pow(Math.random(), 5) * (Math.min(distanceX, distanceY) / 1.8);
     this._startAngle = stage.randomAngle();
     this._endAngle = stage.randomAngle();
     this._omega = (Math.random() - 0.5) * 0.3;
@@ -74,6 +74,8 @@ CanvasArc.prototype.draw = function(context)
     }
 };
 
+// CanvasLinePoint contains no draw() method since it is either moveTo or
+// lineTo depending on its index.
 function CanvasLinePoint(stage, coordinateMaximum)
 {
     var X_LOOPS = 40;
@@ -83,8 +85,8 @@ function CanvasLinePoint(stage, coordinateMaximum)
     var offset = offsets[Math.floor(Math.random() * offsets.length)];
 
     this.coordinate = new Point(X_LOOPS/2, Y_LOOPS/2);
-    if (stage._objects.length) {
-        var head = stage._objects[stage._objects.length - 1].coordinate;
+    if (stage.objects.length) {
+        var head = stage.objects[stage.objects.length - 1].coordinate;
         this.coordinate.x = head.x;
         this.coordinate.y = head.y;
     }
@@ -103,119 +105,116 @@ function CanvasLinePoint(stage, coordinateMaximum)
     var xOff = .25 * (this.coordinate.y % 2);
     var randX = (xOff + this.coordinate.x) * stage.size.x / X_LOOPS;
     var randY = this.coordinate.y * stage.size.y / Y_LOOPS;
-    var colors = ["#101010", "#808080", "#c0c0c0", "#e01040"];
-    this._color = colors[Math.floor(Math.random() * colors.length)];
-
-    this._width = Math.pow(Math.random(), 5) * 20 + 1;
-    this._isSplit = Math.random() > 0.9;
-    this._point = new Point(randX, randY);
+    var colors = ["#101010", "#808080", "#c0c0c0", "#101010", "#808080", "#c0c0c0", "#e01040"];
+    this.color = colors[Math.floor(Math.random() * colors.length)];
 
+    this.width = Math.pow(Math.random(), 5) * 20 + 1;
+    this.isSplit = Math.random() > 0.9;
+    this.point = new Point(randX, randY);
 }
 
-CanvasLinePoint.prototype.draw = function(context, stage)
-{
-    context.lineTo(this._point.x, this._point.y);
-};
-
-
 // === STAGES ===
 
-function SimpleCanvasPathStrokeStage(element, options, canvasObject)
-{
-    SimpleCanvasStage.call(this, element, options, canvasObject);
-    this.context.lineCap = options["lineCap"] || "butt";
-    this.context.lineJoin = options["lineJoin"] || "bevel";
-}
-SimpleCanvasPathStrokeStage.prototype = Object.create(SimpleCanvasStage.prototype);
-SimpleCanvasPathStrokeStage.prototype.constructor = SimpleCanvasPathStrokeStage;
-SimpleCanvasPathStrokeStage.prototype.animate = function() {
-    var context = this.context;
-    var stage = this;
-
-    context.beginPath();
-    this._objects.forEach(function(object, index) {
-        if (index == 0) {
-            context.lineWidth = object._width;
-            context.strokeStyle = object._color;
-            context.moveTo(object._point.x, object._point.y);
-        } else {
-            if (object._isSplit) {
-                context.stroke();
-
-                context.lineWidth = object._width;
-                context.strokeStyle = object._color;
-                context.beginPath();
-            }
-
-            if (Math.random() > 0.999)
-                object._isSplit = !object._isSplit;
-
-            object.draw(context);
+CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage,
+    function()
+    {
+        SimpleCanvasStage.call(this, CanvasLineSegment);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        SimpleCanvasStage.prototype.initialize.call(this, benchmark);
+        this.context.lineCap = benchmark.options["lineCap"] || "butt";
+        this.circleRadius = this.size.x / 3 / 2 - 20;
+    },
+
+    animate: function()
+    {
+        var context = this.context;
+        var stage = this;
+
+        context.clearRect(0, 0, this.size.x, this.size.y);
+        context.lineWidth = 30;
+        for(var i = 0; i < 3; i++) {
+            context.strokeStyle = ["#e01040", "#10c030", "#e05010"][i];
+            context.fillStyle = ["#70051d", "#016112", "#702701"][i];
+            context.beginPath();
+                context.arc((0.5 + i) / 3 * stage.size.x, stage.size.y/2, stage.circleRadius, 0, Math.PI*2);
+            context.stroke();
+            context.fill();
         }
-    });
-    context.stroke();
-}
 
-function CanvasLineSegmentStage(element, options)
-{
-    SimpleCanvasStage.call(this, element, options, CanvasLineSegment);
-    this.context.lineCap = options["lineCap"] || "butt";
-    this.circleRadius = this.size.x / 3 / 2 - 20;
-}
-CanvasLineSegmentStage.prototype = Object.create(SimpleCanvasStage.prototype);
-CanvasLineSegmentStage.prototype.constructor = CanvasLineSegmentStage;
-CanvasLineSegmentStage.prototype.animate = function()
-{
-    var context = this.context;
-    var stage = this;
-
-    context.lineWidth = 30;
-    for(var i = 0; i < 3; i++) {
-        context.strokeStyle = ["#e01040", "#10c030", "#e05010"][i];
-        context.fillStyle = ["#70051d", "#016112", "#702701"][i];
+        this.objects.forEach(function(object) {
+            object.draw(context);
+        });
+    }
+});
+
+CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasStage,
+    function()
+    {
+        SimpleCanvasStage.call(this, CanvasLinePoint);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        SimpleCanvasStage.prototype.initialize.call(this, benchmark);
+        this.context.lineJoin = benchmark.options["lineJoin"] || "bevel";
+        this.context.lineCap = benchmark.options["lineCap"] || "butt";
+    },
+
+    animate: function() {
+        var context = this.context;
+        var stage = this;
+
+        context.clearRect(0, 0, this.size.x, this.size.y);
         context.beginPath();
-            context.arc((0.5 + i) / 3 * stage.size.x, stage.size.y/2, stage.circleRadius, 0, Math.PI*2);
+        this.objects.forEach(function(object, index) {
+            if (index == 0) {
+                context.lineWidth = object.width;
+                context.strokeStyle = object.color;
+                context.moveTo(object.point.x, object.point.y);
+            } else {
+                if (object.isSplit) {
+                    context.stroke();
+
+                    context.lineWidth = object.width;
+                    context.strokeStyle = object.color;
+                    context.beginPath();
+                }
+
+                context.lineTo(object.point.x, object.point.y);
+
+                if (Math.random() > 0.999)
+                    object.isSplit = !object.isSplit;
+            }
+        });
         context.stroke();
-        context.fill();
     }
-
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-}
-
-function CanvasLinePathStage(element, options)
-{
-    SimpleCanvasPathStrokeStage.call(this, element, options, CanvasLinePoint);
-    this.context.lineJoin = options["lineJoin"] || "bevel";
-    this.context.lineCap = options["lineCap"] || "butt";
-}
-CanvasLinePathStage.prototype = Object.create(SimpleCanvasPathStrokeStage.prototype);
-CanvasLinePathStage.prototype.constructor = CanvasLinePathStage;
+});
 
 // === BENCHMARK ===
 
-function CanvasPathBenchmark(suite, test, options, progressBar)
-{
-    SimpleCanvasBenchmark.call(this, suite, test, options, progressBar);
-}
-CanvasPathBenchmark.prototype = Object.create(SimpleCanvasBenchmark.prototype);
-CanvasPathBenchmark.prototype.constructor = CanvasPathBenchmark;
-CanvasPathBenchmark.prototype.createStage = function(element)
-{
-    switch (this._options["pathType"]) {
-    case "line":
-        return new CanvasLineSegmentStage(element, this._options);
-    case "arcs":
-        return new SimpleCanvasStage(element, this._options, CanvasArc);
-    case "linePath":
-        return new CanvasLinePathStage(element, this._options);
+CanvasPathBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        var stage;
+        switch (options["pathType"]) {
+        case "line":
+            stage = new CanvasLineSegmentStage();
+            break;
+        case "linePath":
+            stage = new CanvasLinePathStage();
+            break;
+        case "arcs":
+            stage = new SimpleCanvasStage(CanvasArc);
+            break;
+        }
+
+        Benchmark.call(this, stage, options);
     }
-}
+);
 
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new CanvasPathBenchmark(suite, test, options, progressBar);
-}
+window.benchmarkClass = CanvasPathBenchmark;
 
 })();
\ No newline at end of file
@@ -2,16 +2,15 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/canvas-electrons.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
@@ -8,7 +8,6 @@
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/canvas-stars.js"></script>
 </head>
 <body>
index debf582..6c0778c 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
     <style>
         img {
             position: absolute;
@@ -8,18 +9,16 @@
             height: 80px;
         }
     </style>
-    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <div id="stage"></div>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="../bouncing-particles/resources/bouncing-particles.js"></script>
     <script src="resources/compositing-transforms.js"></script>
-</head>
-<body>
-    <div id="stage"></div>
 </body>
 </html>
diff --git a/PerformanceTests/Animometer/tests/misc/resources/canvas-electrons.js b/PerformanceTests/Animometer/tests/misc/resources/canvas-electrons.js
new file mode 100644 (file)
index 0000000..f15804f
--- /dev/null
@@ -0,0 +1,110 @@
+(function() {
+
+function CanvasElectron(stage)
+{
+    this._context = stage.context;
+    this._stageSize = stage.size;
+
+    var minSide = Math.min(this._stageSize.width, this._stageSize.height);
+    var radiusX = stage.random(minSide / 8, 7 * minSide / 16);
+    var radiusY = stage.random(minSide / 8, 3 * radiusX / 4);
+    this._orbitRadiuses = new Point(radiusX, radiusY);
+    this._radius = stage.random(5, 15);
+    this._direction = stage.randomInt(0, 2);
+    this._angle = stage.randomInt(0, 360);
+    this._color = stage.randomColor();
+    this._rotater = stage.randomRotater();
+    this._rotater.next(stage.random(0, this._rotater.interval));
+}
+
+CanvasElectron.prototype = {
+    _draw: function()
+    {
+        // Calculate the position of the object on the ellipse.
+        var angle = this._direction ? this._rotater.degree() : 360 - this._rotater.degree();
+        var position = this._stageSize.center.subtract(Point.pointOnEllipse(angle, this._orbitRadiuses));
+
+        this._context.save();
+            this._context.translate(this._stageSize.center.x, this._stageSize.center.y);
+            this._context.rotate(this._angle * Math.PI / 180);
+            this._context.translate(-this._stageSize.center.x, -this._stageSize.center.y);
+
+            // Set the stroke and the fill colors
+            this._context.strokeStyle = "rgba(192, 192, 192, 0.9)";
+            this._context.fillStyle = this._color;
+
+            // Draw the orbit of the object.
+            this._context.beginPath();
+            this._context.ellipse(this._stageSize.center.x, this._stageSize.center.y, this._orbitRadiuses.x, this._orbitRadiuses.y, 0, 0, 2 * Math.PI);
+            this._context.stroke();
+
+            // Draw the object.
+            this._context.beginPath();
+            this._context.arc(position.x, position.y, this._radius, 0, Math.PI * 2, true);
+            this._context.fill();
+        this._context.restore();
+    },
+
+    animate: function(timeDelta)
+    {
+        this._rotater.next(timeDelta / 100);
+        this._draw();
+    }
+};
+
+CanvasElectronsStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+        this._electrons = [];
+    }, {
+
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this.context = this.element.getContext("2d");
+    },
+
+    tune: function(count)
+    {
+        if (count == 0)
+            return this._electrons.length;
+
+        if (count > 0) {
+            for (var i = 0; i < count; ++i)
+                this._electrons.push(new CanvasElectron(this));
+            return this._electrons.length;
+        }
+
+        count = Math.min(-count, this._electrons.length);
+        this._electrons.splice(-count, count);
+
+        return this._electrons.length;
+    },
+
+    animate: function(timeDelta)
+    {
+        this.context.clearRect(0, 0, this.size.x, this.size.y);
+
+        // Draw a big star in the middle.
+        this.context.fillStyle = "orange";
+        this.context.beginPath();
+        this.context.arc(this.size.center.x, this.size.center.y, 50, 0, Math.PI * 2, true);
+        this.context.fill();
+
+        this._electrons.forEach(function(electron) {
+            electron.animate(timeDelta);
+        });
+    }
+});
+
+CanvasElectronsBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new CanvasElectronsStage(), options);
+    }
+);
+
+window.benchmarkClass = CanvasElectronsBenchmark;
+
+})();
\ No newline at end of file
diff --git a/PerformanceTests/Animometer/tests/misc/resources/canvas-stars.js b/PerformanceTests/Animometer/tests/misc/resources/canvas-stars.js
new file mode 100644 (file)
index 0000000..e853976
--- /dev/null
@@ -0,0 +1,106 @@
+(function() {
+
+function CanvasStar(stage)
+{
+    this._context = stage.context;
+
+    this._size = stage.randomSquareSize(5, 20);
+    this._center = stage.randomPosition(stage.size.subtract(this._size)).add(this._size.center);
+    this._rotateX = 0;
+    this._rotateDeltaX = stage.random(0.3, 0.7);
+}
+
+CanvasStar.prototype = {
+    _draw: function()
+    {
+        this._context.save();
+        this._context.translate(this._center.x, this._center.y);
+
+        this._context.fillStyle = 'yellow';
+        this._context.strokeStyle = 'white';
+
+        this._context.lineWidth = 1;
+
+        this._context.beginPath();
+        this._context.moveTo(                                     0, -this._size.y /  2);
+        this._context.lineTo(+this._size.x / 20 - this._rotateX / 5, -this._size.y / 10);
+        this._context.lineTo(+this._size.x / 4  - this._rotateX,                      0);
+        this._context.lineTo(+this._size.x / 20 - this._rotateX / 5, +this._size.y / 10);
+        this._context.lineTo(                                     0, +this._size.y /  2);
+        this._context.lineTo(-this._size.x / 20 + this._rotateX / 5, +this._size.y / 10);
+        this._context.lineTo(-this._size.x /  4 + this._rotateX,                      0);
+        this._context.lineTo(-this._size.x / 20 + this._rotateX / 5, -this._size.y / 10);
+        this._context.lineTo(                                     0, -this._size.y /  2);
+
+        this._context.fill();
+        this._context.stroke();
+        this._context.closePath();
+        this._context.restore();
+    },
+
+    animate: function(timeDelta)
+    {
+        this._rotateX += this._rotateDeltaX;
+
+        if (this._rotateX > this._size.x / 4 || this._rotateX < -this._size.x / 4) {
+            this._rotateDeltaX = -this._rotateDeltaX;
+            this._rotateX += this._rotateDeltaX;
+        }
+
+        this._draw();
+    }
+};
+
+CanvasStarsStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+        this._objects = [];
+    }, {
+
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this.context = this.element.getContext("2d");
+    },
+
+    tune: function(count)
+    {
+        if (count == 0)
+            return this._objects.length;
+
+        if (count > 0) {
+            for (var i = 0; i < count; ++i)
+                this._objects.push(new CanvasStar(this));
+            return this._objects.length;
+        }
+
+        count = Math.min(-count, this._objects.length);
+        this._objects.splice(-count, count);
+
+        return this._objects.length;
+    },
+
+    animate: function(timeDelta)
+    {
+        this.context.beginPath();
+        this.context.fillStyle = 'black';
+        this.context.rect(0, 0, this.size.width, this.size.height);
+        this.context.fill();
+
+        this._objects.forEach(function(object) {
+            object.animate(timeDelta);
+        });
+    }
+});
+
+CanvasStarsBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new CanvasStarsStage(), options);
+    }
+);
+
+window.benchmarkClass = CanvasStarsBenchmark;
+
+})();
\ No newline at end of file
index 6249fd6..abd1691 100644 (file)
@@ -1,67 +1,66 @@
-function BouncingCompositedImage(stage)
-{
-    BouncingParticle.call(this, stage);
+(function() {
 
-    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();
-}
+BouncingCompositedImage = Utilities.createSubclass(BouncingParticle,
+    function(stage)
+    {
+        BouncingParticle.call(this, stage);
 
-BouncingCompositedImage.prototype = Object.create(BouncingParticle.prototype);
-BouncingCompositedImage.prototype.constructor = BouncingCompositedImage;
+        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);
 
-BouncingCompositedImage.prototype._move = function()
-{
-    this.element.style.transform = "translate3d(" + this._position.x + "px," + this._position.y + "px, 0) " + this._rotater.rotateZ();
-}
-    
-BouncingCompositedImage.prototype.animate = function(timeDelta)
-{
-    BouncingParticle.prototype.animate.call(this, timeDelta);
-    this._move();
-}
+        if (stage.useFilters)
+            this.element.style.filter = "hue-rotate(" + stage.randomAngle() + "rad)";
 
-function CompositingTransformsStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg";
-    this.useFilters = options["filters"] == "yes";
-}
+        stage.element.appendChild(this.element);
+        this._move();
+    }, {
 
-CompositingTransformsStage.prototype = Object.create(BouncingParticlesStage.prototype);
-CompositingTransformsStage.prototype.constructor = CompositingTransformsStage;
+    _move: function()
+    {
+        this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) " + this.rotater.rotateZ();
+    },
 
-CompositingTransformsStage.prototype.createParticle = function()
-{
-    return new BouncingCompositedImage(this);
-}
+    animate: function(timeDelta)
+    {
+        BouncingParticle.prototype.animate.call(this, timeDelta);
+        this._move();
+    }
+});
 
-CompositingTransformsStage.prototype.particleWillBeRemoved = function(particle)
-{
-    particle.element.remove();
-}
+CompositingTransformsStage = Utilities.createSubclass(BouncingParticlesStage,
+    function()
+    {
+        BouncingParticlesStage.call(this);
+    }, {
 
-function CompositedTransformsBenchmark(suite, test, options, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, progressBar);
-}
+    initialize: function(benchmark)
+    {
+        BouncingParticlesStage.prototype.initialize.call(this, benchmark);
 
-CompositedTransformsBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-CompositedTransformsBenchmark.prototype.constructor = CompositedTransformsBenchmark;
+        this.imageSrc = benchmark.options["imageSrc"] || "../resources/yin-yang.svg";
+        this.useFilters = benchmark.options["filters"] == "yes";
+    },
 
-CompositedTransformsBenchmark.prototype.createStage = function(element)
-{
-    return new CompositingTransformsStage(element, this._options);
-}
+    createParticle: function()
+    {
+        return new BouncingCompositedImage(this);
+    },
 
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new CompositedTransformsBenchmark(suite, test, options, progressBar);
-}
+    particleWillBeRemoved: function(particle)
+    {
+        particle.element.remove();
+    }
+});
+
+CompositedTransformsBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new CompositingTransformsStage(), options);
+    }
+);
+
+window.benchmarkClass = CompositedTransformsBenchmark;
+
+})();
index 4913a2e..74f64ec 100644 (file)
@@ -1,3 +1,37 @@
+function Rotater(rotateInterval)
+{
+    this._timeDelta = 0;
+    this._rotateInterval = rotateInterval;
+}
+
+Rotater.prototype =
+{
+    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 + ")";
+    }
+};
+
 function BenchmarkState(testInterval)
 {
     this._currentTimeOffset = 0;
@@ -9,11 +43,6 @@ BenchmarkState.stages = {
     WARMING: 0,
     SAMPLING: 1,
     FINISHED: 2,
-    messages: [ 
-        Strings.text.runningState.warming,
-        Strings.text.runningState.sampling,
-        Strings.text.runningState.finished
-    ]
 }
 
 BenchmarkState.prototype =
@@ -22,7 +51,7 @@ BenchmarkState.prototype =
     {
         return stage * this._stageInterval;
     },
-    
+
     _message: function(stage, timeOffset)
     {
         if (stage == BenchmarkState.stages.FINISHED)
@@ -32,17 +61,17 @@ BenchmarkState.prototype =
             + Math.floor((timeOffset - this._timeOffset(stage)) / 1000) + "/"
             + Math.floor((this._timeOffset(stage + 1) - this._timeOffset(stage)) / 1000) + ")";
     },
-    
+
     update: function(currentTimeOffset)
     {
         this._currentTimeOffset = currentTimeOffset;
     },
-    
+
     samplingTimeOffset: function()
     {
         return this._timeOffset(BenchmarkState.stages.SAMPLING);
     },
-    
+
     currentStage: function()
     {
         for (var stage = BenchmarkState.stages.WARMING; stage < BenchmarkState.stages.FINISHED; ++stage) {
@@ -50,27 +79,110 @@ BenchmarkState.prototype =
                 return stage;
         }
         return BenchmarkState.stages.FINISHED;
+    }
+}
+
+
+function Stage() {}
+
+Stage.prototype =
+{
+    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;
+    },
+
+    random: function(min, max)
+    {
+        return (Math.random() * (max - min)) + min;
+    },
+
+    randomBool: function()
+    {
+        return !!Math.round(this.random(0, 1));
+    },
+
+    randomInt: function(min, max)
+    {
+        return Math.round(this.random(min, max));
+    },
+
+    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);
     },
-    
-    currentMessage: function()
+
+    randomRotater: function()
     {
-        return this._message(this.currentStage(), this._currentTimeOffset);
+        return new Rotater(this.random(1000, 10000));
     },
-    
-    currentProgress: function()
+
+    tune: function()
     {
-        return this._currentTimeOffset / this._timeOffset(BenchmarkState.stages.FINISHED);
+        throw "Not implemented";
+    },
+
+    animate: function()
+    {
+        throw "Not implemented";
+    },
+
+    clear: function()
+    {
+        return this.tune(-this.tune(0));
     }
-}
+};
 
-function Animator(benchmark, options)
+function Animator()
 {
-    this._benchmark = benchmark;
-    this._options = options;
-    
     this._frameCount = 0;
     this._dropFrameCount = 1;
-    this._measureFrameCount = 3; 
+    this._measureFrameCount = 3;
     this._referenceTime = 0;
     this._currentTimeOffset = 0;
     this._estimator = new KalmanEstimator(60);
@@ -78,12 +190,23 @@ function Animator(benchmark, options)
 
 Animator.prototype =
 {
+    initialize: function(benchmark)
+    {
+        this._benchmark = benchmark;
+        this._estimateFrameRate = benchmark.options["estimated-frame-rate"];
+    },
+
+    get benchmark()
+    {
+        return this._benchmark;
+    },
+
     timeDelta: function()
     {
         return this._currentTimeOffset - this._startTimeOffset;
     },
-    
-    animate: function()
+
+    _shouldRequestAnotherFrame: function()
     {
         var currentTime = performance.now();
         
@@ -108,34 +231,41 @@ Animator.prototype =
         // Get the average FPS of _measureFrameCount frames over measureTimeDelta.
         var measureTimeDelta = this._currentTimeOffset - this._measureTimeOffset;
         var currentFrameRate = Math.floor(1000 / (measureTimeDelta / this._measureFrameCount));
-         
+
         // Use Kalman filter to get a more non-fluctuating frame rate.
-        if (this._options["estimated-frame-rate"])
+        if (this._estimateFrameRate)
             currentFrameRate = this._estimator.estimate(currentFrameRate);
-        
+
         // Adjust the test to reach the desired FPS.
         var result = this._benchmark.update(this._currentTimeOffset, this.timeDelta(), currentFrameRate);
-        
+
         // Start the next drop/measure cycle.
         this._frameCount = 0;
-        
+
         // If result == 0, no more requestAnimationFrame() will be invoked.
         return result;
     },
-    
-    animateLoop: function(timestamp)
+
+    animateLoop: function()
     {
-        if (this.animate())
+        if (this._shouldRequestAnotherFrame()) {
+            this._benchmark.stage.animate(this.timeDelta());
             requestAnimationFrame(this.animateLoop.bind(this));
+        }
     }
 }
 
-function Benchmark(options)
+function Benchmark(stage, options)
 {
     this._options = options;
-    this._recordInterval = 200;    
-    this._isSampling = false;
 
+    this._stage = stage;
+    this._stage.initialize(this);
+    this._animator = new Animator();
+    this._animator.initialize(this);
+
+    this._recordInterval = 200;
+    this._isSampling = false;
     this._controller = new PIDController(this._options["frame-rate"]);
     this._sampler = new Sampler(2);
     this._state = new BenchmarkState(this._options["test-interval"] * 1000);
@@ -143,20 +273,35 @@ function Benchmark(options)
 
 Benchmark.prototype =
 {
+    get options()
+    {
+        return this._options;
+    },
+
+    get stage()
+    {
+        return this._stage;
+    },
+
+    get animator()
+    {
+        return this._animator;
+    },
+
     // Called from the load event listener or from this.run().
     start: function()
     {
         this._animator.animateLoop();
     },
-    
+
     // Called from the animator to adjust the complexity of the test.
     update: function(currentTimeOffset, timeDelta, currentFrameRate)
     {
         this._state.update(currentTimeOffset);
-        
+
         var stage = this._state.currentStage();
         if (stage == BenchmarkState.stages.FINISHED) {
-            this.clear();
+            this._stage.clear();
             return false;
         }
 
@@ -168,8 +313,8 @@ Benchmark.prototype =
         var tuneValue = 0;
         if (this._options["adjustment"] == "fixed") {
             if (this._options["complexity"]) {
-                // this.tune(0) returns the current complexity of the test.
-                tuneValue = this._options["complexity"] - this.tune(0);
+                // this._stage.tune(0) returns the current complexity of the test.
+                tuneValue = this._options["complexity"] - this._stage.tune(0);
             }
         }
         else if (!(this._isSampling && this._options["adjustment"] == "fixed-after-warmup")) {
@@ -179,15 +324,15 @@ Benchmark.prototype =
             tuneValue = tuneValue > 0 ? Math.floor(tuneValue) : Math.ceil(tuneValue);
         }
 
-        var currentComplexity = this.tune(tuneValue);
+        var currentComplexity = this._stage.tune(tuneValue);
         this.record(currentTimeOffset, currentComplexity, currentFrameRate);
         return true;
     },
-    
+
     record: function(currentTimeOffset, currentComplexity, currentFrameRate)
     {
         this._sampler.sample(currentTimeOffset, [currentComplexity, currentFrameRate]);
-        
+
         if (typeof this._recordTimeOffset == "undefined")
             this._recordTimeOffset = currentTimeOffset;
 
@@ -195,10 +340,9 @@ Benchmark.prototype =
         if (stage != BenchmarkState.stages.FINISHED && currentTimeOffset < this._recordTimeOffset + this._recordInterval)
             return;
 
-        this.showResults(this._state.currentProgress(), this._state.currentMessage());
         this._recordTimeOffset = currentTimeOffset;
     },
-    
+
     run: function()
     {
         this.start();
@@ -210,29 +354,8 @@ Benchmark.prototype =
                 return promise.resolve(self._sampler);
             setTimeout(resolveWhenFinished.bind(self), 50);
         }
-        
+
         resolveWhenFinished();
         return promise;
     }
-}
-
-window.benchmarkClient = {};
-
-// This event listener runs the test if it is loaded outside the benchmark runner.
-window.addEventListener("load", function()
-{
-    if (window.self !== window.top)
-        return;
-    window.benchmark = window.benchmarkClient.create(null, null, 30000, 50, null, null);
-    window.benchmark.start();
-});
-
-// This function is called from the suite controller run-callback when running the benchmark runner.
-window.runBenchmark = function(suite, test, options, progressBar)
-{
-    var benchmarkOptions = { complexity: test.complexity };
-    benchmarkOptions = Utilities.mergeObjects(benchmarkOptions, options);
-    benchmarkOptions = Utilities.mergeObjects(benchmarkOptions, Utilities.parseParameters());
-    window.benchmark = window.benchmarkClient.create(suite, test, benchmarkOptions, progressBar);
-    return window.benchmark.run();
-}
+};
diff --git a/PerformanceTests/Animometer/tests/resources/stage.js b/PerformanceTests/Animometer/tests/resources/stage.js
deleted file mode 100644 (file)
index 7b0b114..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-function Rotater(rotateInterval)
-{
-    this._timeDelta = 0;
-    this._rotateInterval = rotateInterval;
-}
-
-Rotater.prototype =
-{
-    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 + ")";
-    }
-}
-
-function Stage(element, options)
-{
-    this.element = element;
-    this._size = Point.elementClientSize(element).subtract(Insets.elementPadding(element).size);
-}
-
-Stage.prototype =
-{
-    get size()
-    {
-        return this._size
-    },
-    
-    random: function(min, max)
-    {
-        return (Math.random() * (max - min)) + min;
-    },
-    
-    randomBool: function()
-    {
-        return !!Math.round(this.random(0, 1));
-    },
-
-    randomInt: function(min, max)
-    {
-        return Math.round(this.random(min, max));
-    },
-    
-    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);
-    },
-    
-    randomRotater: function()
-    {
-        return new Rotater(this.random(1000, 10000));
-    },
-
-    tune: function()
-    {
-        throw "Not implemented";
-    },
-    
-    animate: function()
-    {
-        throw "Not implemented";
-    },
-    
-    clear: function()
-    {
-        return this.tune(-this.tune(0));
-    }
-}
-
-function StageAnimator(benchmark, options)
-{
-    Animator.call(this, benchmark, options);
-};
-
-StageAnimator.prototype = Object.create(Animator.prototype);
-StageAnimator.prototype.constructor = StageAnimator;
-
-StageAnimator.prototype.animate = function()
-{
-    if (!Animator.prototype.animate.call(this))
-        return false;
-    this._benchmark._stage.animate(this.timeDelta());
-    return true;
-}
-
-function StageBenchmark(suite, test, options, progressBar)
-{
-    Benchmark.call(this, options);
-    
-    var element = document.getElementById("stage");
-    element.setAttribute("width", document.body.offsetWidth);
-    element.setAttribute("height", document.body.offsetHeight);
-    
-    this._stage = this.createStage(element);
-    this._animator = this.createAnimator();
-    this._suite = suite;
-    this._test = test;
-    this._progressBar = progressBar;
-}
-
-StageBenchmark.prototype = Object.create(Benchmark.prototype);
-StageBenchmark.prototype.constructor = StageBenchmark;
-
-StageBenchmark.prototype.createStage = function(element)
-{
-    return new Stage(element, this._options);
-}
-
-StageBenchmark.prototype.createAnimator = function()
-{
-    return new StageAnimator(this, this._options);
-}
-
-StageBenchmark.prototype.tune = function(count)
-{
-    return this._stage.tune(count);
-}
-
-StageBenchmark.prototype.clear = function()
-{
-    return this._stage.clear();
-}
-
-StageBenchmark.prototype.showResults = function(progress, message)
-{
-    if (!this._progressBar || !this._test)
-        return;
-
-    this._progressBar.setPos(progress);
-}
index 1dad205..a743a2b 100644 (file)
@@ -1,3 +1,5 @@
+(function() {
+
 // === PAINT OBJECTS ===
 
 function CanvasLineSegment(stage) {
@@ -172,124 +174,162 @@ CanvasRectFill.prototype.draw = function(context) {
 
 // === STAGES ===
 
-function SimpleCanvasPathStrokeStage(element, options, canvasObject) {
-    SimpleCanvasStage.call(this, element, options, canvasObject);
-}
-SimpleCanvasPathStrokeStage.prototype = Object.create(SimpleCanvasStage.prototype);
-SimpleCanvasPathStrokeStage.prototype.constructor = SimpleCanvasPathStrokeStage;
-SimpleCanvasPathStrokeStage.prototype.animate = function() {
-    var context = this.context;
-    context.lineWidth = this.randomInt(1, 20);
-    context.strokeStyle = this.randomColor();
-    context.beginPath();
-    context.moveTo(0,0);
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-    context.stroke();
-}
+SimpleCanvasPathStrokeStage = Utilities.createSubclass(SimpleCanvasStage,
+    function(canvasObject) {
+        SimpleCanvasStage.call(this, canvasObject);
+    }, {
 
-function SimpleCanvasPathFillStage(element, options, canvasObject) {
-    SimpleCanvasStage.call(this, element, options, canvasObject);
-}
-SimpleCanvasPathFillStage.prototype = Object.create(SimpleCanvasStage.prototype);
-SimpleCanvasPathFillStage.prototype.constructor = SimpleCanvasPathFillStage;
-SimpleCanvasPathFillStage.prototype.animate = function() {
-    var context = this.context;
-    context.fillStyle = this.randomColor();
-    context.beginPath();
-    context.moveTo(0,0);
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-    context.fill();
-}
+    animate: function()
+    {
+        var context = this.context;
+        context.clearRect(0, 0, this.size.x, this.size.y);
+        context.lineWidth = this.randomInt(1, 20);
+        context.strokeStyle = this.randomColor();
+        context.beginPath();
+        context.moveTo(0,0);
+        this.objects.forEach(function(object) {
+            object.draw(context);
+        });
+        context.stroke();
+    }
+});
 
-function CanvasLineSegmentStage(element, options)
-{
-    SimpleCanvasStage.call(this, element, options, CanvasLineSegment);
-    this.context.lineCap = options["lineCap"] || "butt";
-}
-CanvasLineSegmentStage.prototype = Object.create(SimpleCanvasStage.prototype);
-CanvasLineSegmentStage.prototype.constructor = CanvasLineSegmentStage;
+SimpleCanvasPathFillStage = Utilities.createSubclass(SimpleCanvasStage,
+    function(canvasObject) {
+        SimpleCanvasStage.call(this, canvasObject);
+    }, {
 
-function CanvasLinePathStage(element, options)
-{
-    SimpleCanvasPathStrokeStage.call(this, element, options, CanvasLinePoint);
-    this.context.lineJoin = options["lineJoin"] || "bevel";
-}
-CanvasLinePathStage.prototype = Object.create(SimpleCanvasPathStrokeStage.prototype);
-CanvasLinePathStage.prototype.constructor = CanvasLinePathStage;
-
-function CanvasLineDashStage(element, options)
-{
-    SimpleCanvasStage.call(this, element, options, CanvasLinePoint);
-    this.context.setLineDash([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-    this.context.lineWidth = 1;
-    this.context.strokeStyle = "#000";
-    this._step = 0;
-}
-CanvasLineDashStage.prototype = Object.create(SimpleCanvasStage.prototype);
-CanvasLineDashStage.prototype.constructor = CanvasLineDashStage;
-CanvasLineDashStage.prototype.animate = function() {
-    var context = this.context;
-    context.lineDashOffset = this._step++;
-    context.beginPath();
-    context.moveTo(0,0);
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-    context.stroke();
-};
+    animate: function()
+    {
+        var context = this.context;
+        context.clearRect(0, 0, this.size.x, this.size.y);
+        context.fillStyle = this.randomColor();
+        context.beginPath();
+        context.moveTo(0,0);
+        this.objects.forEach(function(object) {
+            object.draw(context);
+        });
+        context.fill();
+    }
+});
 
-// === BENCHMARK ===
+CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage,
+    function()
+    {
+        SimpleCanvasStage.call(this, CanvasLineSegment);
+    }, {
 
-function CanvasPathBenchmark(suite, test, options, progressBar) {
-    SimpleCanvasBenchmark.call(this, suite, test, options, progressBar);
-}
-CanvasPathBenchmark.prototype = Object.create(SimpleCanvasBenchmark.prototype);
-CanvasPathBenchmark.prototype.constructor = CanvasPathBenchmark;
-CanvasPathBenchmark.prototype.createStage = function(element)
-{
-    switch (this._options["pathType"]) {
-    case "line":
-        return new CanvasLineSegmentStage(element, this._options);
-    case "linePath": {
-        if ("lineJoin" in this._options)
-            return new CanvasLinePathStage(element, this._options);
-        if ("lineDash" in this._options)
-            return new CanvasLineDashStage(element, this._options);
-        break;
+    initialize: function(benchmark)
+    {
+        SimpleCanvasStage.prototype.initialize.call(this, benchmark);
+        this.context.lineCap = benchmark.options["lineCap"] || "butt";
     }
-    case "quadratic":
-        return new SimpleCanvasStage(element, this._options, CanvasQuadraticSegment);
-    case "quadraticPath":
-        return new SimpleCanvasPathStrokeStage(element, this._options, CanvasQuadraticPoint);
-    case "bezier":
-        return new SimpleCanvasStage(element, this._options, CanvasBezierSegment);
-    case "bezierPath":
-        return new SimpleCanvasPathStrokeStage(element, this._options, CanvasBezierPoint);
-    case "arcTo":
-        return new SimpleCanvasStage(element, this._options, CanvasArcToSegment);
-    case "arc":
-        return new SimpleCanvasStage(element, this._options, CanvasArcSegment);
-    case "rect":
-        return new SimpleCanvasStage(element, this._options, CanvasRect);
-    case "lineFill":
-        return new SimpleCanvasPathFillStage(element, this._options, CanvasLinePoint);
-    case "quadraticFill":
-        return new SimpleCanvasPathFillStage(element, this._options, CanvasQuadraticPoint);
-    case "bezierFill":
-        return new SimpleCanvasPathFillStage(element, this._options, CanvasBezierPoint);
-    case "arcToFill":
-        return new SimpleCanvasStage(element, this._options, CanvasArcToSegmentFill);
-    case "arcFill":
-        return new SimpleCanvasStage(element, this._options, CanvasArcSegmentFill);
-    case "rectFill":
-        return new SimpleCanvasStage(element, this._options, CanvasRectFill);
+});
+
+CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasPathStrokeStage,
+    function()
+    {
+        SimpleCanvasPathStrokeStage.call(this, CanvasLinePoint);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        SimpleCanvasPathStrokeStage.prototype.initialize.call(this, benchmark);
+        this.context.lineJoin = benchmark.options["lineJoin"] || "bevel";
     }
-}
+});
 
-window.benchmarkClient.create = function(suite, test, options, progressBar) {
-    return new CanvasPathBenchmark(suite, test, options, progressBar);
-}
+CanvasLineDashStage = Utilities.createSubclass(SimpleCanvasStage,
+    function()
+    {
+        SimpleCanvasStage.call(this, CanvasLinePoint);
+        this._step = 0;
+    }, {
+
+    initialize: function(benchmark)
+    {
+        SimpleCanvasStage.prototype.initialize.call(this, benchmark);
+        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(0,0);
+        this.objects.forEach(function(object) {
+            object.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 "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;
+        }
+
+        Benchmark.call(this, stage, options);
+    }
+);
+
+window.benchmarkClass = CanvasPathBenchmark;
+
+})();
\ No newline at end of file
index 55f4a86..14a4454 100644 (file)
@@ -1,62 +1,20 @@
-
-function SimpleCanvasStage(element, options, canvasObject)
-{
-    Stage.call(this, element, options);
-    this.context = this.element.getContext("2d");
-    this.canvasObject = canvasObject;
-    this._objects = [];
-}
-SimpleCanvasStage.prototype = Object.create(Stage.prototype);
-SimpleCanvasStage.prototype.constructor = SimpleCanvasStage;
-SimpleCanvasStage.prototype.tune = function(count)
-{
-    if (count == 0)
-        return this._objects.length;
-
-    if (count > 0) {
-        // For path-based tests, use the object length as a maximum coordinate value
-        // to make it easier to see what the test is doing
-        var coordinateMaximum = Math.max(this._objects.length, 200);
-        for (var i = 0; i < count; ++i) {
-            this._objects.push(new this.canvasObject(this, coordinateMaximum));
+Utilities.extendObject(SimpleCanvasStage.prototype, {
+    tune: function(count)
+    {
+        if (count == 0)
+            return this.objects.length;
+
+        if (count > 0) {
+            // For path-based tests, use the object length as a maximum coordinate value
+            // to make it easier to see what the test is doing
+            var coordinateMaximum = Math.max(this.objects.length, 200);
+            for (var i = 0; i < count; ++i)
+                this.objects.push(new this._canvasObject(this, coordinateMaximum));
+            return this.objects.length;
         }
-        return this._objects.length;
-    }
-
-    count = Math.min(-count, this._objects.length);
-    this._objects.splice(-count, count);
-
-    return this._objects.length;
-}
-SimpleCanvasStage.prototype.animate = function()
-{
-    var context = this.context;
-    this._objects.forEach(function(object) {
-        object.draw(context);
-    });
-}
-
-function SimpleCanvasAnimator(benchmark, options)
-{
-    StageAnimator.call(this, benchmark, options);
-    this._context = benchmark._stage.context;
-}
-
-SimpleCanvasAnimator.prototype = Object.create(StageAnimator.prototype);
-SimpleCanvasAnimator.prototype.constructor = SimpleCanvasAnimator;
-SimpleCanvasAnimator.prototype.animate = function()
-{
-    this._context.clearRect(0, 0, this._benchmark._stage.size.x, this._benchmark._stage.size.y);
-    return StageAnimator.prototype.animate.call(this, this._options);
-}
-
-
-function SimpleCanvasBenchmark(suite, test, options, progressBar) {
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-SimpleCanvasBenchmark.prototype = Object.create(StageBenchmark.prototype);
-SimpleCanvasBenchmark.prototype.constructor = SimpleCanvasBenchmark;
-SimpleCanvasBenchmark.prototype.createAnimator = function() {
-    return new SimpleCanvasAnimator(this, this._options);
-}
 
+        count = Math.min(-count, this.objects.length);
+        this.objects.splice(-count, count);
+        return this.objects.length;
+    }
+});
index 0d597fb..4a2da8f 100644 (file)
@@ -2,17 +2,17 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
+    <script src="../master/resources/canvas-stage.js"></script>
     <script src="resources/simple-canvas.js"></script>
     <script src="resources/simple-canvas-paths.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
index 3c889ee..4250e39 100644 (file)
+(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.
-}
+TemplateCanvasObject.prototype = {
+    _draw: function()
+    {
+        // Draw your object.
+    },
 
-TemplateCanvasObject.prototype.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();
-}
+    animate: function(timeDelta)
+    {
+        // Redraw the animated object. The last time this animated
+        // item was drawn before 'timeDelta'.
 
-function TemplateCanvasStage(element, options)
-{
-    Stage.call(this, element, options);
-    this.context = this.element.getContext("2d");
+        // Move your object.
 
-    // Define a collection for your objects.
-}
+        // Redraw your object.
+        this._draw();
+    }
+};
 
-TemplateCanvasStage.prototype = Object.create(Stage.prototype);
-TemplateCanvasStage.prototype.constructor = TemplateCanvasStage;
+TemplateCanvasStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+    }, {
 
-TemplateCanvasStage.prototype.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.
-    
-    // Return the number of all the elements in the stage.
-    // This number is recorded in the sampled data.
-    
-    // Return the count of the objects in the stage.
-    return 0;
-}
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this.context = this.element.getContext("2d");
 
-TemplateCanvasStage.prototype.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.
+        // Define a collection for your objects.
+    },
 
-    // Loop through all your objects and ask them to animate.
-}
+    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.
 
-function TemplateCanvasAnimator(benchmark, options)
-{
-    Animator.call(this, benchmark, options);
-    this._context = benchmark._stage.context;
-}
-
-TemplateCanvasAnimator.prototype = Object.create(StageAnimator.prototype);
-TemplateCanvasAnimator.prototype.constructor = TemplateCanvasAnimator;
+        // Change objects in the stage.
 
-TemplateCanvasAnimator.prototype.animate = function()
-{
-    // Most likely you will need to clear the canvas with every redraw.
-    this._context.clearRect(0, 0, this._benchmark._stage.size.x, this._benchmark._stage.size.y);
+        // Return the number of all the elements in the stage.
+        // This number is recorded in the sampled data.
 
-    // Draw scene stuff here if needed.
+        // Return the count of the objects in the stage.
+        return 0;
+    },
 
-    return StageAnimator.prototype.animate.call(this);
-}
+    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.
 
-function TemplateCanvasBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
+        // Most likely you will need to clear the canvas with every redraw.
+        this.context.clearRect(0, 0, this.size.x, this.size.y);
 
-TemplateCanvasBenchmark.prototype = Object.create(StageBenchmark.prototype);
-TemplateCanvasBenchmark.prototype.constructor = TemplateCanvasBenchmark;
+        // Loop through all your objects and ask them to animate.
+    }
+});
 
-TemplateCanvasBenchmark.prototype.createStage = function(element)
-{
-    // Attach the stage to the benchmark.
-    return new TemplateCanvasStage(element, this._options);
-}
+TemplateCanvasBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new TemplateCanvasStage(), options);
+    }
+);
 
-TemplateCanvasBenchmark.prototype.createAnimator = function()
-{
-    // Attach the animator to the benchmark.
-    return new TemplateCanvasAnimator(this, this._options);
-}
+window.benchmarkClass = TemplateCanvasBenchmark;
 
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    // This function is called from the test harness which starts the
-    // test by creating your benchmark object.
-    return new TemplateCanvasBenchmark(suite, test, options, progressBar);
-}
+})();
\ No newline at end of file
index 2e3c955..6c077fa 100644 (file)
@@ -1,55 +1,52 @@
-function TemplateCssStage(element, options)
-{
-    Stage.call(this, element, options);
-}
-
-TemplateCssStage.prototype = Object.create(Stage.prototype);
-TemplateCssStage.prototype.constructor = TemplateCssStage;
-
-TemplateCssStage.prototype.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.
-    
-    // Return the number of all the elements in the stage.
-    // This number is recorded in the sampled data.
-    
-    // Return the count of the objects in the stage.
-    return 0;
-}
-
-TemplateCssStage.prototype.animate = function(timeDelta)
-{
-    // Animate the elements such that all of them are redrawn. You 
-    // may need to define your object so it keeps its animation data.
-    // This object should encapsulate a corrosponding HTMLElement.
-    // You may also define a method called animate() in this object
-    // and just call this function here for all the elements.
-    
-    // Loop through all your objects and ask them to animate.
-}
-
-function TemplateCssBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-TemplateCssBenchmark.prototype = Object.create(StageBenchmark.prototype);
-TemplateCssBenchmark.prototype.constructor = TemplateCssBenchmark;
-
-TemplateCssBenchmark.prototype.createStage = function(element)
-{
-    // You need to override this method such that your stage is hooked
-    // up to the benchmark.
-    return new TemplateCssStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    // This function is called from the test harness which starts the
-    // test by creating your benchmark object.
-    return new TemplateCssBenchmark(suite, test, options, progressBar);
-}
+(function() {
+
+TemplateCssStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+
+        // Do initialization here.
+    },
+
+    tune: function(count)
+    {
+        // If count is -ve, -count elements need to be removed form the
+        // stage. If count is +ve, +count elements need to be added to
+        // the stage.
+
+        // Change objects in the stage.
+
+        // Return the number of all the elements in the stage.
+        // This number is recorded in the sampled data.
+
+        // Return the count of the objects in the stage.
+        return 0;
+    },
+
+    animate: function(timeDelta)
+    {
+        // Animate the elements such that all of them are redrawn. You
+        // may need to define your object so it keeps its animation data.
+        // This object should encapsulate a corrosponding HTMLElement.
+        // You may also define a method called animate() in this object
+        // and just call this function here for all the elements.
+
+        // Loop through all your objects and ask them to animate.
+    }
+});
+
+TemplateCssBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new TemplateCssStage(), options);
+    }
+);
+
+window.benchmarkClass = TemplateCssBenchmark;
+
+})();
index a88add7..7fdadbb 100644 (file)
@@ -1,55 +1,52 @@
-function TemplateSvgStage(element, options)
-{
-    Stage.call(this, element, options);
-}
-
-TemplateSvgStage.prototype = Object.create(Stage.prototype);
-TemplateSvgStage.prototype.constructor = TemplateSvgStage;
-
-TemplateSvgStage.prototype.tune = function(count)
-{
-    // If count is -ve, -count elements need to be removed form the
-    // stage. If count is +ve, +count elements need to be added to
-    // the stage.
-    
-    // TODO: Change objects in the stage.
-    
-    // Return the number of all the elements in the stage.
-    // This number is recorded in the sampled data.
-    
-    // TODO: Return the count of the objects in the stage.
-    return 0;
-}
-
-TemplateSvgStage.prototype.animate = function(timeDelta)
-{
-    // Animate the elements such that all of them are redrawn. You 
-    // may need to define your object so it keeps its animation data.
-    // This object should encapsulate a corrosponding SVGElement.
-    // You may also define a method called animate() in this object
-    // and just call this function here for all the elements.
-    
-    // TODO: Loop through all your objects and ask them to animate.
-}
-
-function TemplateSvgBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-TemplateSvgBenchmark.prototype = Object.create(StageBenchmark.prototype);
-TemplateSvgBenchmark.prototype.constructor = TemplateSvgBenchmark;
-
-TemplateSvgBenchmark.prototype.createStage = function(element)
-{
-    // You need to override this method such that your stage is hooked
-    // up to the benchmark.
-    return new TemplateSvgStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    // This function is called from the test harness which starts the
-    // test by creating your benchmark object.
-    return new TemplateSvgBenchmark(suite, test, options, progressBar);
-}
+(function() {
+
+TemplateSvgStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+
+        // Do initialization here.
+    },
+
+    tune: function(count)
+    {
+        // If count is -ve, -count elements need to be removed form the
+        // stage. If count is +ve, +count elements need to be added to
+        // the stage.
+
+        // TODO: Change objects in the stage.
+
+        // Return the number of all the elements in the stage.
+        // This number is recorded in the sampled data.
+
+        // TODO: Return the count of the objects in the stage.
+        return 0;
+    },
+
+    animate: function(timeDelta)
+    {
+        // Animate the elements such that all of them are redrawn. You
+        // may need to define your object so it keeps its animation data.
+        // This object should encapsulate a corrosponding SVGElement.
+        // You may also define a method called animate() in this object
+        // and just call this function here for all the elements.
+
+        // TODO: Loop through all your objects and ask them to animate.
+    }
+});
+
+TemplateSvgBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new TemplateSvgStage(), options);
+    }
+);
+
+window.benchmarkClass = TemplateSvgBenchmark;
+
+})();
index c17d7f9..b87ba79 100644 (file)
@@ -2,16 +2,15 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/template-canvas.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
index 1b9b0fb..90bf2e9 100644 (file)
@@ -2,16 +2,15 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <div id="stage"></div>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/template-css.js"></script>
-</head>
-<body>
-    <div id="stage"></div>
 </body>
 </html>
index a81f808..2e0df9a 100644 (file)
@@ -2,16 +2,15 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <svg id="stage"></svg>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>
     <script src="resources/template-svg.js"></script>
-</head>
-<body>
-    <svg id="stage"></svg>
 </body>
 </html>
index 32da2ac..fbff373 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
     <style>
         .text-layer {
             position: absolute;
                 font-size: 0.96em;
             }
         }
-    </style>  
-    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+    </style>
+</head>
+<body>
+    <div id="stage"></div>
     <script src="../../resources/algorithm.js"></script>
     <script src="../../resources/strings.js"></script>
     <script src="../../resources/sampler.js"></script>
     <script src="../../resources/extensions.js"></script>
     <script src="../resources/math.js"></script>
     <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
     <script src="resources/layering-text.js"></script>
-</head>
-<body>
-    <div id="stage"></div>
 </body>
 </html>
index e2b7ba9..138b046 100644 (file)
-function LayeringTextStage(element, options)
-{
-    Stage.call(this, element, options);
-    this._textElementParent = this.element;
-    this._textElements = [];
-    this._textItemIndex = 0;
-    this._colorIndex = 0;
-    this._animateCounts = 0;
-}
-
-LayeringTextStage.textItems = [
-    "<div class='text-layer'>",
-        "<h2>Types of benchmarks</h2>",
-        "<ol>",
-            "<li>Real program",
-                "<ul>",
-                    "<li>word processing software</li>",
-                    "<li>tool software of CAD</li>",
-                    "<li>user's application software (i.e.: MIS)</li>",
-                "</ul>",
-            "</li>",
-            "<li>Kernel",
-                "<ul>",
-                    "<li>contains key codes</li>",
-                    "<li>normally abstracted from actual program</li>",
-                    "<li>popular kernel: Livermore loop</li>",
-                    "<li>linpack benchmark (contains basic linear algebra subroutine written in FORTRAN language)</li>",
-                    "<li>results are represented in MFLOPS</li>",
-                "</ul>",
-            "</li>",
-            "<li>Synthetic Benchmark",
-                "<ul>",
-                    "<li>Procedure for programming synthetic benchmark:",
-                        "<ul>",
-                            "<li>take statistics of all types of operations from many application programs</li>",
-                            "<li>get proportion of each operation</li>",
-                            "<li>write program based on the proportion above</li>",
-                        "</ul>",
-                    "</li>",
-                    "<li>Types of Synthetic Benchmark are:",
-                        "<ul>",
-                            "<li>Whetstone</li>",
-                            "<li>Dhrystone</li>",
-                        "</ul>",
-                    "</li>",
-                    "<li>These were the first general purpose industry standard computer benchmarks. They do not necessarily obtain high scores on modern pipelined computers.</li>",
-                "</ul>",
-            "</li>",
-            "<li>I/O benchmarks</li>",
-            "<li>Database benchmarks: to measure the throughput and response times of database management systems (DBMS')</li>",
-            "<li>Parallel benchmarks: used on machines with multiple cores, processors or systems consisting of multiple machines</li>",
-        "</ol>",
-        "<h2>Common benchmarks</h2>",
-        "<ul>",
-            "<li>Business Applications Performance Corporation (BAPCo)</li>",
-            "<li>Embedded Microprocessor Benchmark Consortium (EEMBC)</li>",
-            "<li>Standard Performance Evaluation Corporation (SPEC), in particular their SPECint and SPECfp</li>",
-            "<li>Transaction Processing Performance Council (TPC)</li>",
-            "<li>Coremark: Embedded computing benchmark</li>",
-        "</ul>",
-        "<h3>Open source benchmarks</h3>",
-        "<ul>",
-            "<li>AIM Multiuser Benchmark: composed of a list of tests that could be mixed to create a 'load mix' that would simulate a specific computer function on any UNIX-type OS.</li>",
-            "<li>Bonnie++: filesystem and hard drive benchmark</li>",
-            "<li>BRL-CAD: cross-platform architecture-agnostic benchmark suite based on multithreaded ray tracing performance; baselined against a VAX-11/780; and used since 1984 for evaluating relative CPU performance, compiler differences, optimization levels, coherency, architecture differences, and operating system differences.</li>",
-        "</ul>",
-    "</div>"
-];
-
-LayeringTextStage.parseTextItem = function(textItem)
-{
-    var parseResult = {};
-    parseResult.tagStart = textItem.match(/<(.*?)>/g)[0];
-    var spaceIndex = parseResult.tagStart.indexOf(" ");
-    parseResult.nodeName = parseResult.tagStart.substring(1, spaceIndex != -1 ? spaceIndex : parseResult.tagStart.length - 1);
-    parseResult.args = spaceIndex != -1 ? Utilities.parseArguments(parseResult.tagStart.substring(spaceIndex + 1, parseResult.tagStart.length - 1)) : {};
-    var tagEnd = "</" + parseResult.nodeName + ">";                
-    parseResult.tagEnd = textItem.endsWith(tagEnd) ? tagEnd : "";
-    return parseResult;
-}
-
-LayeringTextStage.isOpeningTextItem = function(textItem)
-{
-    return !LayeringTextStage.parseTextItem(textItem).tagEnd.length;
-}
-
-LayeringTextStage.isClosingTextItem = function(textItem)
-{
-    return textItem.indexOf("/") == +1;
-}
-
-LayeringTextStage.textItemsFlags = LayeringTextStage.textItems.map(function(textItem)
-{
-   var textItemFlags = {};
-   textItemFlags.isOpening = LayeringTextStage.isOpeningTextItem(textItem);
-   textItemFlags.isClosing = LayeringTextStage.isClosingTextItem(textItem);   
-   return textItemFlags;
-});
+(function() {
+
+LayeringTextStage = Utilities.createSubclass(Stage,
+    function()
+    {
+        Stage.call(this);
+    }, {
+
+    initialize: function(benchmark)
+    {
+        Stage.prototype.initialize.call(this, benchmark);
+        this._textElementParent = this.element;
+        this._textElements = [];
+        this._textItemIndex = 0;
+        this._colorIndex = 0;
+        this._animateCounts = 0;
+    },
+
+    _nextTextItem: function(textItemFlags)
+    {
+        var textItem = LayeringTextStage.textItems[this._textItemIndex];
+        Utilities.extendObject(textItemFlags, LayeringTextStage.textItemsFlags[this._textItemIndex]);
+        this._textItemIndex = (this._textItemIndex + 1) % LayeringTextStage.textItems.length;
+        return textItem;
+    },
+
+    _previousTextItem: function(textItemFlags)
+    {
+        this._textItemIndex = (this._textItemIndex + LayeringTextStage.textItems.length - 1) % LayeringTextStage.textItems.length;
+        Utilities.extendObject(textItemFlags, LayeringTextStage.textItemsFlags[this._textItemIndex]);
+        return LayeringTextStage.textItems[this._textItemIndex];
+    },
+
+    _pushTextElement: function()
+    {
+        var textItemFlags = {};
+        var textItem = this._nextTextItem(textItemFlags);
+        for ( ; textItemFlags.isClosing; textItem = this._nextTextItem(textItemFlags))
+            this._textElementParent = this._textElementParent.parentNode;
+
+        var parseResult = LayeringTextStage.parseTextItem(textItem);
+        textItem = textItem.substring(parseResult.tagStart.length, textItem.length - parseResult.tagEnd.length);
+
+        var textElement = document.createElement(parseResult.nodeName);
+
+        for (var attrname in parseResult.args)
+            textElement.setAttribute(attrname, parseResult.args[attrname]);
+
+        this._textElementParent.appendChild(textElement);
+
+        if (!parseResult.tagEnd.length)
+            this._textElementParent = textElement;
+
+        textElement.innerHTML = textItem;
+
+        this._textElements.push(textElement);
+        return this._textElements.length;
+    },
 
-LayeringTextStage.isColorableTextItem = function(textItemFlags)
-{
-    return !(textItemFlags.isOpening || textItemFlags.isClosing);
-}
-
-LayeringTextStage.isInsertableTextItem = function(textItemFlags)
-{
-    return !textItemFlags.isClosing;
-}
-
-LayeringTextStage.colorableTextItems = LayeringTextStage.textItemsFlags.filter(function(textItemFlags)
-{
-    return LayeringTextStage.isColorableTextItem(textItemFlags);
-}).length;
-
-LayeringTextStage.insertableTextItems = LayeringTextStage.textItemsFlags.filter(function(textItemFlags)
-{
-    return LayeringTextStage.isInsertableTextItem(textItemFlags);
-}).length;
-
-LayeringTextStage.colorIndexToTextElementIndex = function(colorIndex)
-{
-    var textElementIndex = 0;
-    var index = 0;
-    
-    for (var textItemIndex = 0; textItemIndex < LayeringTextStage.textItemsFlags.length; ++textItemIndex) {
-        if (LayeringTextStage.isColorableTextItem(LayeringTextStage.textItemsFlags[textItemIndex])) {
-            if (++index > colorIndex)
-                break;
-        }
-        if (LayeringTextStage.isInsertableTextItem(LayeringTextStage.textItemsFlags[textItemIndex]))
-            ++textElementIndex;
-    }
-    
-    return textElementIndex;
-}
-
-LayeringTextStage.prototype = Object.create(Stage.prototype);
-LayeringTextStage.prototype.constructor = LayeringTextStage;
-
-LayeringTextStage.prototype._nextTextItem = function(textItemFlags)
-{
-    var textItem = LayeringTextStage.textItems[this._textItemIndex];
-    Utilities.extendObject(textItemFlags, LayeringTextStage.textItemsFlags[this._textItemIndex]);
-    this._textItemIndex = (this._textItemIndex + 1) % LayeringTextStage.textItems.length;
-    return textItem;
-}
-
-LayeringTextStage.prototype._previousTextItem = function(textItemFlags)
-{
-    this._textItemIndex = (this._textItemIndex + LayeringTextStage.textItems.length - 1) % LayeringTextStage.textItems.length;
-    Utilities.extendObject(textItemFlags, LayeringTextStage.textItemsFlags[this._textItemIndex]);    
-    return LayeringTextStage.textItems[this._textItemIndex];
-}
-
-LayeringTextStage.prototype._pushTextElement = function()
-{
-    var textItemFlags = {};
-    var textItem = this._nextTextItem(textItemFlags);
-    for ( ; textItemFlags.isClosing; textItem = this._nextTextItem(textItemFlags))
-        this._textElementParent = this._textElementParent.parentNode;
-
-    var parseResult = LayeringTextStage.parseTextItem(textItem);
-    textItem = textItem.substring(parseResult.tagStart.length, textItem.length - parseResult.tagEnd.length);
-
-    var textElement = document.createElement(parseResult.nodeName);
-
-    for (var attrname in parseResult.args)
-        textElement.setAttribute(attrname, parseResult.args[attrname]);
-
-    this._textElementParent.appendChild(textElement);
-    
-    if (!parseResult.tagEnd.length)
-        this._textElementParent = textElement;
-
-    textElement.innerHTML = textItem;
-    
-    this._textElements.push(textElement);
-    return this._textElements.length;
-}
-
-LayeringTextStage.prototype._popTextElement = function()
-{
-    var textItemFlags = {};    
-    var textItem = this._previousTextItem(textItemFlags);
-    for ( ; textItemFlags.isClosing; textItem = this._previousTextItem(textItemFlags))
-        this._textElementParent = this._textElementParent.lastChild;
-
-    if (textItemFlags.isOpening)
-        this._textElementParent = this._textElementParent.parentNode;
-
-    this._textElements[this._textElements.length - 1].remove();
-
-    this._textElements.pop();
-    return this._textElements.length;
-}
-
-LayeringTextStage.prototype._colorTextItem = function(color)
-{
-    var textElementIndex = LayeringTextStage.colorIndexToTextElementIndex(this._colorIndex);
-    for ( ; textElementIndex < this._textElements.length; textElementIndex += LayeringTextStage.insertableTextItems)
-        this._textElements[textElementIndex].style.backgroundColor = color;
-}
-
-LayeringTextStage.prototype.animate = function(timeDelta)
-{
-    this._colorTextItem("transparent");
-    this._colorIndex = (this._colorIndex + 1) % LayeringTextStage.colorableTextItems;
-    this._colorTextItem("YellowGreen");
-    
-    var blackTextElements = Math.min(this._textElements.length, LayeringTextStage.insertableTextItems);
-    var i = 0;
-    for ( ; i < this._textElements.length - blackTextElements; ++i)
-        this._textElements[i].style.color = (this._animateCounts & 1) ? "LightYellow" : "white";
-
-    for ( ; i < this._textElements.length; ++i)
-        this._textElements[i].style.color = "black";
-        
-    ++this._animateCounts;
-}
-
-LayeringTextStage.prototype.tune = function(count)
-{
-    if (count == 0)
+    _popTextElement: function()
+    {
+        var textItemFlags = {};
+        var textItem = this._previousTextItem(textItemFlags);
+        for ( ; textItemFlags.isClosing; textItem = this._previousTextItem(textItemFlags))
+            this._textElementParent = this._textElementParent.lastChild;
+
+        if (textItemFlags.isOpening)
+            this._textElementParent = this._textElementParent.parentNode;
+
+        this._textElements[this._textElements.length - 1].remove();
+
+        this._textElements.pop();
         return this._textElements.length;
+    },
+
+    _colorTextItem: function(color)
+    {
+        var textElementIndex = LayeringTextStage.colorIndexToTextElementIndex(this._colorIndex);
+        for ( ; textElementIndex < this._textElements.length; textElementIndex += LayeringTextStage.insertableTextItems)
+            this._textElements[textElementIndex].style.backgroundColor = color;
+    },
+
+    animate: function(timeDelta)
+    {
+        this._colorTextItem("transparent");
+        this._colorIndex = (this._colorIndex + 1) % LayeringTextStage.colorableTextItems;
+        this._colorTextItem("YellowGreen");
+
+        var blackTextElements = Math.min(this._textElements.length, LayeringTextStage.insertableTextItems);
+        var i = 0;
+        for ( ; i < this._textElements.length - blackTextElements; ++i)
+            this._textElements[i].style.color = (this._animateCounts & 1) ? "LightYellow" : "white";
+
+        for ( ; i < this._textElements.length; ++i)
+            this._textElements[i].style.color = "black";
+
+        ++this._animateCounts;
+    },
+
+    tune: function(count)
+    {
+        if (count == 0)
+            return this._textElements.length;
+
+        if (count > 0) {
+            for (var i = 0; i < count; ++i)
+                this._pushTextElement();
+            return this._textElements.length;
+        }
 
-    if (count > 0) {
+        count = Math.min(-count, this._textElements.length);
         for (var i = 0; i < count; ++i)
-            this._pushTextElement();
+            this._popTextElement();
+
         return this._textElements.length;
     }
-        
-    count = Math.min(-count, this._textElements.length);
-    for (var i = 0; i < count; ++i)
-        this._popTextElement();
-
-    return this._textElements.length;
-}
-
-function LayeringTextBenchmark(suite, test, options, progressBar)
-{
-    StageBenchmark.call(this, suite, test, options, progressBar);
-}
-
-LayeringTextBenchmark.prototype = Object.create(StageBenchmark.prototype);
-LayeringTextBenchmark.prototype.constructor = LayeringTextBenchmark;
-
-LayeringTextBenchmark.prototype.createStage = function(element)
-{
-    return new LayeringTextStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, progressBar)
-{
-    return new LayeringTextBenchmark(suite, test, options, progressBar);
-}
+});
+
+Utilities.extendObject(LayeringTextStage, {
+    textItems: [
+        "<div class='text-layer'>",
+            "<h2>Types of benchmarks</h2>",
+            "<ol>",
+                "<li>Real program",
+                    "<ul>",
+                        "<li>word processing software</li>",
+                        "<li>tool software of CAD</li>",
+                        "<li>user's application software (i.e.: MIS)</li>",
+                    "</ul>",
+                "</li>",
+                "<li>Kernel",
+                    "<ul>",
+                        "<li>contains key codes</li>",
+                        "<li>normally abstracted from actual program</li>",
+                        "<li>popular kernel: Livermore loop</li>",
+                        "<li>linpack benchmark (contains basic linear algebra subroutine written in FORTRAN language)</li>",
+                        "<li>results are represented in MFLOPS</li>",
+                    "</ul>",
+                "</li>",
+                "<li>Synthetic Benchmark",
+                    "<ul>",
+                        "<li>Procedure for programming synthetic benchmark:",
+                            "<ul>",
+                                "<li>take statistics of all types of operations from many application programs</li>",
+                                "<li>get proportion of each operation</li>",
+                                "<li>write program based on the proportion above</li>",
+                            "</ul>",
+                        "</li>",
+                        "<li>Types of Synthetic Benchmark are:",
+                            "<ul>",
+                                "<li>Whetstone</li>",
+                                "<li>Dhrystone</li>",
+                            "</ul>",
+                        "</li>",
+                        "<li>These were the first general purpose industry standard computer benchmarks. They do not necessarily obtain high scores on modern pipelined computers.</li>",
+                    "</ul>",
+                "</li>",
+                "<li>I/O benchmarks</li>",
+                "<li>Database benchmarks: to measure the throughput and response times of database management systems (DBMS')</li>",
+                "<li>Parallel benchmarks: used on machines with multiple cores, processors or systems consisting of multiple machines</li>",
+            "</ol>",
+            "<h2>Common benchmarks</h2>",
+            "<ul>",
+                "<li>Business Applications Performance Corporation (BAPCo)</li>",
+                "<li>Embedded Microprocessor Benchmark Consortium (EEMBC)</li>",
+                "<li>Standard Performance Evaluation Corporation (SPEC), in particular their SPECint and SPECfp</li>",
+                "<li>Transaction Processing Performance Council (TPC)</li>",
+                "<li>Coremark: Embedded computing benchmark</li>",
+            "</ul>",
+            "<h3>Open source benchmarks</h3>",
+            "<ul>",
+                "<li>AIM Multiuser Benchmark: composed of a list of tests that could be mixed to create a 'load mix' that would simulate a specific computer function on any UNIX-type OS.</li>",
+                "<li>Bonnie++: filesystem and hard drive benchmark</li>",
+                "<li>BRL-CAD: cross-platform architecture-agnostic benchmark suite based on multithreaded ray tracing performance; baselined against a VAX-11/780; and used since 1984 for evaluating relative CPU performance, compiler differences, optimization levels, coherency, architecture differences, and operating system differences.</li>",
+            "</ul>",
+        "</div>"
+    ],
+
+    parseTextItem: function(textItem)
+    {
+        var parseResult = {};
+        parseResult.tagStart = textItem.match(/<(.*?)>/g)[0];
+        var spaceIndex = parseResult.tagStart.indexOf(" ");
+        parseResult.nodeName = parseResult.tagStart.substring(1, spaceIndex != -1 ? spaceIndex : parseResult.tagStart.length - 1);
+        parseResult.args = spaceIndex != -1 ? Utilities.parseArguments(parseResult.tagStart.substring(spaceIndex + 1, parseResult.tagStart.length - 1)) : {};
+        var tagEnd = "</" + parseResult.nodeName + ">";
+        parseResult.tagEnd = textItem.endsWith(tagEnd) ? tagEnd : "";
+        return parseResult;
+    },
+
+    isOpeningTextItem: function(textItem)
+    {
+        return !LayeringTextStage.parseTextItem(textItem).tagEnd.length;
+    },
+
+    isClosingTextItem: function(textItem)
+    {
+        return textItem.indexOf("/") == +1;
+    },
+
+    isColorableTextItem: function(textItemFlags)
+    {
+        return !(textItemFlags.isOpening || textItemFlags.isClosing);
+    },
+
+    isInsertableTextItem: function(textItemFlags)
+    {
+        return !textItemFlags.isClosing;
+    },
+
+    colorIndexToTextElementIndex: function(colorIndex)
+    {
+        var textElementIndex = 0;
+        var index = 0;
+
+        for (var textItemIndex = 0; textItemIndex < LayeringTextStage.textItemsFlags.length; ++textItemIndex) {
+            if (LayeringTextStage.isColorableTextItem(LayeringTextStage.textItemsFlags[textItemIndex])) {
+                if (++index > colorIndex)
+                    break;
+            }
+            if (LayeringTextStage.isInsertableTextItem(LayeringTextStage.textItemsFlags[textItemIndex]))
+                ++textElementIndex;
+        }
+
+        return textElementIndex;
+    }
+});
+
+Utilities.extendObject(LayeringTextStage, {
+    textItemsFlags: LayeringTextStage.textItems.map(function(textItem)
+    {
+       var textItemFlags = {};
+       textItemFlags.isOpening = LayeringTextStage.isOpeningTextItem(textItem);
+       textItemFlags.isClosing = LayeringTextStage.isClosingTextItem(textItem);
+       return textItemFlags;
+    })
+});
+
+Utilities.extendObject(LayeringTextStage, {
+    colorableTextItems: LayeringTextStage.textItemsFlags.filter(function(textItemFlags)
+    {
+        return LayeringTextStage.isColorableTextItem(textItemFlags);
+    }).length,
+
+    insertableTextItems: LayeringTextStage.textItemsFlags.filter(function(textItemFlags)
+    {
+        return LayeringTextStage.isInsertableTextItem(textItemFlags);
+    }).length
+});
+
+LayeringTextBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new LayeringTextStage(), options);
+    }
+);
+
+window.benchmarkClass = LayeringTextBenchmark;
+
+})();
+
index e90ae71..6a3523e 100644 (file)
@@ -1,65 +1,58 @@
-function BouncingTextBox(stage, sampleText)
-{
-    BouncingParticle.call(this, stage);
-
-    this.element = document.createElement("div");
-    this.element.classList.add('particle');
-    this.element.style.width = this._size.x + "px";
-    this.element.style.height = this._size.y + "px";
-    this.element.textContent = sampleText;
-    
-    stage.element.appendChild(this.element);
-    this._move();
-}
-
-BouncingTextBox.prototype = Object.create(BouncingParticle.prototype);
-BouncingTextBox.prototype.constructor = BouncingTextBox;
-
-BouncingTextBox.prototype._move = function()
-{
-    this.element.style.left = this._position.x + "px";
-    this.element.style.top = this._position.y + "px";
-}
-    
-BouncingTextBox.prototype.animate = function(timeDelta)
-{
-    BouncingParticle.prototype.animate.call(this, timeDelta);
-    this._move();
-}
-
-function BouncingTextBoxStage(element, options)
-{
-    BouncingParticlesStage.call(this, element, options);
-    this._sampleText = document.getElementById('sample-text').textContent;
-}
-
-BouncingTextBoxStage.prototype = Object.create(BouncingParticlesStage.prototype);
-BouncingTextBoxStage.prototype.constructor = BouncingTextBoxStage;
-
-BouncingTextBoxStage.prototype.createParticle = function()
-{
-    return new BouncingTextBox(this, this._sampleText);
-}
-
-BouncingTextBoxStage.prototype.particleWillBeRemoved = function(particle)
-{
-    particle.element.remove();
-}
-
-function BouncingTextBoxsBenchmark(suite, test, options, recordTable, progressBar)
-{
-    BouncingParticlesBenchmark.call(this, suite, test, options, recordTable, progressBar);
-}
-
-BouncingTextBoxsBenchmark.prototype = Object.create(BouncingParticlesBenchmark.prototype);
-BouncingTextBoxsBenchmark.prototype.constructor = BouncingTextBoxsBenchmark;
-
-BouncingTextBoxsBenchmark.prototype.createStage = function(element)
-{
-    return new BouncingTextBoxStage(element, this._options);
-}
-
-window.benchmarkClient.create = function(suite, test, options, recordTable, progressBar)
-{
-    return new BouncingTextBoxsBenchmark(suite, test, options, recordTable, progressBar);
-}
+(function() {
+
+BouncingTextBox = Utilities.createSubclass(BouncingParticle,
+    function(stage, sampleText)
+    {
+        BouncingParticle.call(this, stage);
+
+        this.element = document.createElement("div");
+        this.element.classList.add('particle');
+        this.element.style.width = this.size.x + "px";
+        this.element.style.height = this.size.y + "px";
+        this.element.textContent = sampleText;
+
+        stage.element.appendChild(this.element);
+        this._move();
+    }, {
+
+    _move: function()
+    {
+        this.element.style.left = this.position.x + "px";
+        this.element.style.top = this.position.y + "px";
+    },
+
+    animate: function(timeDelta)
+    {
+        BouncingParticle.prototype.animate.call(this, timeDelta);
+        this._move();
+    }
+});
+
+BouncingTextBoxStage = Utilities.createSubclass(BouncingParticlesStage,
+    function()
+    {
+        BouncingParticlesStage.call(this);
+        this._sampleText = document.getElementById('sample-text').textContent;
+    }, {
+
+    createParticle: function()
+    {
+        return new BouncingTextBox(this, this._sampleText);
+    },
+
+    particleWillBeRemoved: function(particle)
+    {
+        particle.element.remove();
+    }
+});
+
+BouncingTextBoxBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new BouncingTextBoxStage(), options);
+    }
+);
+
+window.benchmarkClass = BouncingTextBoxBenchmark;
+
+})();
index 7881cf3..6c106f8 100644 (file)
@@ -18,7 +18,7 @@
                 font-size: 0.96em;
             }
         }
-        
+
         .particle {
             position: absolute;
             width: 280px;
             font-family: sans-serif;
             padding: 3px;
         }
-        
+
         #sample-text {
             display: none;
         }
-    </style>  
+    </style>
     <link rel="stylesheet" type="text/css" href="../resources/stage.css">
-    <script src="../../resources/algorithm.js"></script>
-    <script src="../../resources/strings.js"></script>
-    <script src="../../resources/sampler.js"></script>
-    <script src="../../resources/extensions.js"></script>
-    <script src="../resources/math.js"></script>
-    <script src="../resources/utilities.js"></script>    
-    <script src="../resources/main.js"></script>
-    <script src="../resources/stage.js"></script>  
-    <script src="../bouncing-particles/resources/bouncing-particles.js"></script>
-    <script charset="utf-8" src="resources/text-boxes.js"></script>
 </head>
 <body>
     <div id="sample-text" class="particle">I can eat glass and it doesn't hurt me.
         私はガラスを食べられます。それは私を傷つけません。
         나는 유리를 먹을 수 있어요. 그래도 아프지 않아요
         Я можу їсти скло, і воно мені не зашкодить.
-        ನನಗೆ ಹಾನಿ ಆಗದೆ, ನಾನು ಗಜನ್ನು ತಿನಬಹುದು 
+        ನನಗೆ ಹಾನಿ ಆಗದೆ, ನಾನು ಗಜನ್ನು ತಿನಬಹುದು
     </div>
     <div id="stage"></div>
+    <script src="../../resources/algorithm.js"></script>
+    <script src="../../resources/strings.js"></script>
+    <script src="../../resources/sampler.js"></script>
+    <script src="../../resources/extensions.js"></script>
+    <script src="../resources/math.js"></script>
+    <script src="../resources/main.js"></script>
+    <script src="../bouncing-particles/resources/bouncing-particles.js"></script>
+    <script charset="utf-8" src="resources/text-boxes.js"></script>
 </body>
 </html>
index 33e7619..da7e86f 100644 (file)
@@ -1,3 +1,268 @@
+2015-12-27  Jon Lee  <jonlee@apple.com>
+
+        Simplify the test harness
+        https://bugs.webkit.org/show_bug.cgi?id=152562
+
+        Reviewed by Simon Fraser.
+
+        All of the benchmarks use the default Animator(). Don't require new tests
+        to pass a new instance, and instead just make one in the Benchmark constructor.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:
+        * Animometer/tests/master/resources/canvas-tests.js:
+        * Animometer/tests/misc/resources/canvas-electrons.js:
+        * Animometer/tests/misc/resources/canvas-stars.js:
+        * Animometer/tests/misc/resources/compositing-transforms.js:
+        * Animometer/tests/resources/main.js:
+        * Animometer/tests/simple/resources/simple-canvas-paths.js:
+        * Animometer/tests/template/resources/template-canvas.js:
+        * Animometer/tests/template/resources/template-css.js:
+        * Animometer/tests/template/resources/template-svg.js:
+        * Animometer/tests/text/resources/layering-text.js:
+        * Animometer/tests/text/resources/text-boxes.js:
+
+        Refactor the template.
+
+        * Animometer/tests/template/resources/template-canvas.js:
+        * Animometer/tests/template/resources/template-css.js:
+        * Animometer/tests/template/resources/template-svg.js:
+        * Animometer/tests/template/template-canvas.html:
+        * Animometer/tests/template/template-css.html:
+        * Animometer/tests/template/template-svg.html:
+
+        Refactor the SVG suite.
+
+        * Animometer/tests/bouncing-particles/bouncing-svg-images.html: Move scripts to the end.
+        * Animometer/tests/bouncing-particles/bouncing-svg-shapes.html: Ditto.
+
+        * Animometer/tests/bouncing-particles/bouncing-canvas-shapes.html: Remove extraneous includes
+        to stage.js.
+        * Animometer/tests/text/text-boxes.html: Ditto.
+
+        BouncingCanvasParticlesBenchmark is not necessary. Use Benchmark directly when subclassing.
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js: Remove
+        BouncingCanvasParticlesBenchmark.
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js: Use Benchmark.
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js: Ditto.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-particles.js: Require the shape
+        in the constructor instead of having subclasses set the private variable.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js: Refactor.
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:
+
+        Refactor the HTML suite.
+
+        Move scripts to the end.
+        * Animometer/tests/bouncing-particles/bouncing-css-images.html:
+        * Animometer/tests/bouncing-particles/bouncing-css-shapes.html:
+        * Animometer/tests/text/layering-text.html:
+        * Animometer/tests/text/text-boxes.html:
+
+        Refactor to use the new variables.
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
+        * Animometer/tests/text/resources/layering-text.js:
+        * Animometer/tests/text/resources/text-boxes.js:
+
+        Refactor the bouncing canvas tests.
+
+        * Animometer/tests/bouncing-particles/bouncing-canvas-images.html: Move scripts to the end.
+        * Animometer/tests/bouncing-particles/bouncing-canvas-shapes.html: Move scripts to the end.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-particles.js: Promote a few
+        properties to "public" since they are used by subclasses.
+        (BouncingParticlesStage): Fix the constructor, which was missing "this". Make particles
+        "public" for subclasses.
+        (BouncingParticlesStage.initialize): Fix the max velocity, which was accidentally changed.
+        * Animometer/tests/misc/resources/compositing-transforms.js: Refactor.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js:
+        BouncingCanvasParticlesAnimator is no longer needed.
+        (BouncingCanvasParticle): Change constructor to take a shape as a parameter instead of
+        having subclasses set the variable.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js: Refactor.
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js: Refactor.
+
+        Move example/ files into misc/.
+
+        * Animometer/tests/misc/canvas-electrons.html: Renamed from PerformanceTests/Animometer/tests/examples/canvas-electrons.html.
+        * Animometer/tests/misc/canvas-stars.html: Renamed from PerformanceTests/Animometer/tests/examples/canvas-stars.html.
+        * Animometer/tests/misc/resources/canvas-electrons.js: Renamed from PerformanceTests/Animometer/tests/examples/resources/canvas-electrons.js.
+        * Animometer/tests/misc/resources/canvas-stars.js: Renamed from PerformanceTests/Animometer/tests/examples/resources/canvas-stars.js.
+
+        * Animometer/resources/debug-runner/tests.js: Update test URLs.
+
+        Refactor miscellaneous suite.
+
+        * Animometer/tests/bouncing-particles/resources/bouncing-particles.js:
+        Remove BouncingParticlesAnimator and BouncingParticleBenchmark, which are
+        not needed.
+        (tune): Remove console assert.
+        * Animometer/tests/resources/main.js: Add Rotater back in from stage.js.
+
+        * Animometer/tests/examples/resources/canvas-electrons.js: Remove CanvasElectronsAnimator.
+        * Animometer/tests/examples/resources/canvas-stars.js: Remove CanvasStarsAnimator.
+        * Animometer/tests/misc/resources/compositing-transforms.js:
+        * Animometer/tests/examples/canvas-electrons.html: Move scripts to the end.
+        * Animometer/tests/examples/canvas-stars.html: Ditto.
+        * Animometer/tests/misc/compositing-transforms.html: Ditto.
+
+        Refactor the simple suite.
+
+        * Animometer/tests/master/resources/canvas-stage.js:
+        (tune): Remove coordinateMaximum since it is not needed in any
+        of the master tests.
+        * Animometer/tests/simple/resources/simple-canvas.js:
+        SimpleCanvasAnimator and SimpleCanvasBenchmark are no longer
+        needed.
+        (tune): Manage the objects differently, but instead of duplicating
+        all of SimpleCanvasStage here, just replace tune(). Include
+        coordinateMaximum, and remove items from the end of the list
+        instead of the beginning.
+        (StageBenchmark.call.createAnimator): Deleted.
+        (StageBenchmark.call): Deleted.
+        * Animometer/tests/simple/resources/simple-canvas-paths.js:
+        * Animometer/tests/simple/simple-canvas-paths.html: Move
+        scripts to the end.
+
+        Get rid of stage.js, StageAnimator, and StageBenchmark. Don't have the progress bar update during the test.
+
+        * Animometer/resources/debug-runner/animometer.js:
+        (initialize): Move the setting of testsCount to the debug runner.
+        (didRunTest): Nicer name.
+        * Animometer/resources/debug-runner/benchmark-runner.js:
+        (BenchmarkRunner.prototype._runBenchmarkAndRecordResults): Don't pass in the progress bar to benchmarks.
+        * Animometer/resources/extensions.js:
+        (ProgressBar): Refactor. Make variables "private". Resetting the progress when instantiating.
+        (ProgressBar.prototype.incrementRange): This is called every time a benchmark completes.
+        * Animometer/resources/runner/animometer.js:
+        (window.benchmarkRunnerClient.initialize): Remove unneeded setting of testsCount.
+        * Animometer/resources/strings.js: These are no longer needed.
+        * Animometer/tests/master/canvas-stage.html: Remove script inclusion. Other tests will follow.
+        * Animometer/tests/master/resources/canvas-tests.js: Use Benchmark instead of StageBenchmark.
+        * Animometer/tests/resources/main.js: Messages are no longer needed
+        (Animator.prototype._shouldRequestAnotherFrame): Rename from animate(), since this method returns a boolean
+        indicating whether another frame should be requested. Collapse the logic from StageAnimator into animateLoop.
+        (BenchmarkState.prototype.currentStage): Deleted.
+        (BenchmarkState.prototype.currentMessage): Deleted.
+        (BenchmarkState.prototype.currentProgress): Deleted.
+        (Animator.prototype.animate): Deleted.
+        (Animator.prototype.animateLoop): The stage is animated only when we have another frame to draw.
+        (Benchmark.prototype.record): No need to update the progress bar.
+        * Animometer/tests/resources/stage.js: Removed. Rotater will appear in a later patch, in main.js.
+
+        * Animometer/resources/debug-runner/benchmark-runner.js:
+        (BenchmarkRunner.prototype._runBenchmarkAndRecordResults): Each test is run as a benchmark.
+        Remove the call to runBenchmark by merging the options here, and calling benchmark.run()
+        directly.
+
+        Make the class relationships more easily understandable. The benchmark owns the stage,
+        animator, and options. Make the stage and animator no longer have their own references to
+        the options. Make Stage a first-class citizen by promoting it to main.js. Later patches
+        will try to get rid of stage.js altogether.
+        * Animometer/tests/resources/main.js:
+        (Stage): Moved from stage.js.
+        (Animator): Don't pass in benchmark and options in its constructor. It will get initialized
+        by benchmark-related parameters in initialize().
+        (Animator.prototype.initialize): Add a back-reference to benchmark and cache an option.
+        (Animator.prototype.get benchmark):
+        (Animator.prototype.animate): Refactor to use the cached option, to remove its dependency on
+        the options dictionary.
+        (Benchmark): Require all benchmarks to have a stage and animator. The instance will initialize
+        them.
+        (Benchmark.prototype.get options):
+        (Benchmark.prototype.get stage): BenchmarkStates.stages will need to be renamed to avoid confusion.
+        (Benchmark.prototype.get animator):
+        (Benchmark.prototype.start):
+        (Benchmark.prototype.update): Ask the stage directly to tune or clear instead of adding another
+        level of indirection.
+        (window.runBenchmark): Deleted. Remove the need for a benchmarkClient. Also remove the standalone
+        path, since tests can be individually selected, and remove the need for runBenchmark since that is
+        handled in BenchmarkRunner._runBenchmarkAndRecordResults.
+        * Animometer/tests/resources/stage.js:
+        (Stage): Deleted. Moved to main.js.
+        (StageBenchmark): What's left is updating the progress bar; to be removed.
+        (StageAnimator): What's left can be folded in Animator.
+
+        Refactor master suite.
+        * Animometer/tests/master/resources/canvas-stage.js: This now only has SimpleCanvasStage.
+        (animate): Push the clearRect() into each stage.
+        (complexity):
+        (StageBenchmark.call.createAnimator): Deleted.
+        (StageBenchmark.call): Deleted.
+        * Animometer/tests/master/resources/canvas-tests.js: SimpleCanvasPathStrokeStage is no longer needed.
+        (CanvasLineSegment.prototype.draw):
+        (CanvasArc):
+        (CanvasLinePoint): Remove the draw call because depending on its index it either needs to be moveTo
+        or lineTo, and it is otherwise a very small draw operation that doesn't need the overhead of the
+        function call. Do all of the drawing through the stage.
+
+        Refactor the subclass pattern. Introduce Utilities.createSubclass().
+
+        * Animometer/resources/debug-runner/benchmark-runner.js:
+        * Animometer/resources/extensions.js:
+        (window.Utilities.createSubclass): Takes the super class, a function representing
+        the class's constructor, and additional methods to attach to the new class's
+        prototype object.
+        * Animometer/tests/text/text-boxes.html: Remove unneeded reference to utilities.js.
+
+        Refactor tests.
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-particles.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-canvas-shapes.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-css-shapes.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-particles.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-images.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-particles.js:
+        * Animometer/tests/bouncing-particles/resources/bouncing-svg-shapes.js:
+        * Animometer/tests/examples/resources/canvas-electrons.js:
+        * Animometer/tests/examples/resources/canvas-stars.js:
+        * Animometer/tests/master/resources/canvas-stage.js:
+        * Animometer/tests/master/resources/canvas-tests.js:
+        * Animometer/tests/misc/resources/compositing-transforms.js:
+        * Animometer/tests/resources/stage.js:
+        * Animometer/tests/simple/resources/simple-canvas-paths.js:
+        * Animometer/tests/simple/resources/simple-canvas.js:
+        * Animometer/tests/template/resources/template-canvas.js:
+        * Animometer/tests/template/resources/template-css.js:
+        * Animometer/tests/template/resources/template-svg.js:
+        * Animometer/tests/text/resources/layering-text.js: Reorder some of the methods
+        and properties since they rely on each other.
+        * Animometer/tests/text/resources/text-boxes.js:
+
+        * Animometer/resources/debug-runner/animometer.js: Arrange calls
+        in the order they are evoked.
+        * Animometer/resources/debug-runner/benchmark-runner.js:
+        (BenchmarkRunnerState.prototype.next): Get rid of return value since
+        no caller to next() uses it.
+        (BenchmarkRunnerState.prototype.prepareCurrentTest): Refactor the
+        promise to resolve simply when onload() is called instead of
+        looking for #stage.
+        (BenchmarkRunner.prototype._runTestAndRecordResults): Suite.run
+        simply calls runBenchmark(). Call it directly rather than through
+        the Suite.
+        (BenchmarkRunner.prototype.step): Remove unused parameter in
+        resolve callback.
+        (BenchmarkRunner.prototype.runMultipleIterations): Use this instead
+        of self since it is outside of the closure which needed the self
+        variable.
+        (resolveIfReady): Deleted.
+        (BenchmarkRunner.prototype.waitForElement): Deleted.
+        * Animometer/resources/runner/tests.js: prepare() and run() are
+        no longer needed.
+        (Suite.prototype.prepare): Deleted.
+        (Suite.prototype.run): Deleted.
+        * Animometer/tests/master/canvas-stage.html: Move all scripts to
+        the end of the page.
+
 2015-12-23  Simon Fraser  <simon.fraser@apple.com>
 
         Add an Animometer developer test which animates text-rich boxes