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 48fd067ff7b3948888c84b9232b9553b84355b18..48d523a9f39e0b8cdbd9bd182915f7a67e71711f 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 0f793c555b7228e11dfe2b029925b5f28bd984b4..376b51b255ca968b3bfff3e6be93c8494c75c2ea 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 082e8b7d24481f40b08a04b613a1a9d85fda577f..f5497105d2d9b46e3c88561a7bf084d2379ff95d 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 738ab44a9103fcdcb418d06178348e8752c3a4ef..84cc1fd1ce016d1438ca6176f38290f0d37eea1f 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 0498135c07572a70cda0738ebdac53c8f901e9ee..e9d602d23113ed8642da0a14860850b8bcc8d436 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 f984181165c2c7db1b0ce1bdfdc15e1bd9118304..ff08faa3c032dc1cffe01cdb62092fb79c8e972a 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 8293cbed5c723b6f0d1764e02a2850f12a3e35f9..81f46be291815c38d6c4a6645746491ac98f3f2f 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 ad806dbdc8b4239f2ac9ab6f6ea224a959c48dd5..600485faadc656917f7c81843c548e28e078ebd7 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 d1d7c06783da4aea8dca8190cda1d1b216845c25..170edf876e94e94894048c61d56ce285f04b7dc0 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 961bcfc91a1b9e33144859e189c9e2bb146c405d..b3a7bdab35af5c46510558b0f4bf26e71d90ccb3 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 4eab1c2aebdfbe58ae0656b3520a885dcac89e18..39a428c1f0d1a36ffbe02037403d2052ae333c08 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 52dc155f94c384eb0290be9a71f943fb1bb7c49a..23da735dc3fc3b158f44be9c57ae4a8dc17daa8f 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 d579b71eca3a170f9d0ba5cf8aff418e4ff6b2c3..7d32b4e016ce43705e848bd1d7723b5ca77ac410 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 28a78115497b12e94f198ccc87a3c9e7258c33af..d1eb1116858f77190d0fd74b98db29e1a6cdfd8e 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 0b40da269526f2dcffd5f1f5621aff47a0bd7b8b..9b18944d225f411bf681de6dfaa31d82cbaed179 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 be4a1d9cbb3e51bae134eb15c97886ae749c76e7..13b172712359d9c5a83abbe25a184832d38f626d 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 0d3ae24125c808ac169758b2ef11e1e7b67863f4..4d006c393333f71dc1b4faa654a4aede779867e0 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 6f9433555a97966a72e0db5c3acd9de62ab44955..141e2824210677b9734bd464cf61c08be8818e16 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 a0f7bfd0bd53fc15c8e0f51f99bdf916ec2588f6..50e65cc18065681fd0e1e0ff9bd3b31db5c91e56 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 435f2ce563448ff24469ffd5a00e9bb1457a9bb6..e331cc40756b27a9a2eca99ff6fc5632c70c5d3d 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 69c675415b89bb392ae5aabd5511d9efd20646ad..e39f2f0b059edd43a8ef6f3d423b3a36c644fecf 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 d02801aac296dde8de3504bbcba69b62008128ac..88cebaa1ab4101dcf7c98591e121d828f6590777 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 3f46ae94b5bf5d85e308d78165946d2570fa84ab..cd063465287c6dc63e7fd887678e36970d086e3d 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 cee8fca5cca44cf330d151a2c82ed49799947871..53db13ce6fbf20a88a73db131dfd778505e959dd 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 564b58a3c6fbb6ad5871aaa7fdd175b68c287cff..c3d74b141b9db2ed8cf164901ac0d7a5cef734f2 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
similarity index 91%
rename from PerformanceTests/Animometer/tests/examples/canvas-electrons.html
rename to PerformanceTests/Animometer/tests/misc/canvas-electrons.html
index 0909732e1a435bcde9960d775daf7edcd11332ca..34da03a7f9e66b06994d91549d310cdc01f40c33 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/canvas-electrons.js"></script>
-</head>
-<body>
-    <canvas id="stage"></canvas>
 </body>
 </html>
similarity index 91%
rename from PerformanceTests/Animometer/tests/examples/canvas-stars.html
rename to PerformanceTests/Animometer/tests/misc/canvas-stars.html
index 52ad8f83ff38038f7edaef48db2a9d1cd71ad055..1abcb114e565d34c7f882f0852d7e93191bbc487 100644 (file)
@@ -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 debf5826242afc85fe4dab4be93c8db45333be9b..6c0778c7ff6886925246046ea4a1c86743bb539e 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 6249fd6cd60b4459cd4e07b1ede104a399a4df28..abd1691a95bcc6887f5600285d39698c80de4d9b 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 4913a2e6dd714ba1e49110409fe63ecef24cc0f4..74f64ecc38e1373f0800e6231b69ebf17ceed542 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 1dad205bfea4735c07a6f386fd205ba8c8d6841b..a743a2b6f3104f9788619fc91da128b8656b62d7 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 55f4a86b38b8fba5c0800555e19edfdc79401d3a..14a4454555549e0784f64ffc136a703f408c33e0 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 0d597fb88614675548dc1f4cd1e7369c188668df..4a2da8f6e7609f762ecc29b6a1d9dc150582f4b1 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 3c889ee777f00edd682d56f63d809f64022749a5..4250e39852c1233891583e3f1b51cac117bb11de 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 2e3c95544e6c917252de14c43422d1878af2663a..6c077fa913f5a8ce3a6a45bad249a0d060ef46c2 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 a88add7667893f7436db900892ab7bf5bc8101a6..7fdadbb94c51239ab6299bacc233c17a7fe9859e 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 c17d7f988fe55a4ea1c1707a8abb52cf0fef6007..b87ba7954503e38078b9dc66ab129983154423dd 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 1b9b0fbdd8e3f856e2e1a8e8e3eedf096ee8f631..90bf2e9bff767216739076290d0e5a20c096ecc3 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 a81f808287f2ac7b4f7fe9edb45fdef81e49e3b8..2e0df9a51465c2a90ee0e23a26540acc1ca53256 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 32da2ac55d3fe016744b0649665d70322b90c66a..fbff373e51f3475be9edd1d7b9a8d6195dbd3db8 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 e2b7ba99288f006cf106cb6c1349f9cdfa8e40b8..138b04629778c9fa7699b7d55d003f3f8a1a69d6 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 e90ae71793e0cf7efe022e1157a92d433c8dde83..6a3523e017c8e50c6ae8c80d24478923343b6576 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 7881cf3acdeea092e9adf79a2c5dddaf2d590f55..6c106f88edd58d321dfbd47144bad1e406e43835 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 33e7619054dc45518f70cc32555d7c8d178e42cc..da7e86f87e0e7e1ee15909586b1db84c720fed41 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