From: jonlee@apple.com Date: Tue, 13 Oct 2015 01:11:45 +0000 (+0000) Subject: Add basic canvas tests X-Git-Url: http://git.webkit.org/?p=WebKit-https.git;a=commitdiff_plain;h=bbd608d90816b31f9c807f1f3e82075b919d8a37 Add basic canvas tests https://bugs.webkit.org/show_bug.cgi?id=150066 rdar://problem/23081143 Reviewed by Dean Jackson. This adds a new test suite that will cover all of the path-based canvas calls. The patch will be divided up to cover tests with similar techniques. The simplest version uses a SimpleCanvasStage. * Animometer/runner/resources/tests.js: Add tests for quadratic, bezier, arcTo, arc, and rect segments. Also include arcTo, arc, and rect fills. * Animometer/tests/resources/stage.js: (Stage.prototype.randomBool): Added for counterclockwise property for arc segments. (Stage.prototype.randomInt): Fix how values are rounded, used by randomBool. It should round instead of flooring everything. * Animometer/tests/simple/resources/simple-canvas.js: Added. Defines common classes used by all simple canvas tests. The page reads best bottom to top. (SimpleCanvasStage): Basic stage. Pass a canvasObject which will be used to create new objects as needed in tune(). (SimpleCanvasStage.prototype.tune): Modeled on other tests. Adds and removed objects as specified by the provided |count|. (SimpleCanvasStage.prototype.animate): Iterate over all the objects and ask them to draw. There is no "animating" of the objects; they will just paint statically on the canvas. (SimpleCanvasAnimator): Basic animator clears the canvas prior to painting. (SimpleCanvasBenchmark): Hard-code the feedback loop parameters instead of including them in the query parameters to the test URLs. (SimpleCanvasBenchmark.prototype.createAnimator): * Animometer/tests/simple/simple-canvas-paths.html: Added. * Animometer/tests/simple/resources/simple-canvas-paths.js: Added. There is no "animating" of these objects--they just paint statically on the canvas. (CanvasQuadraticSegment): Paint a quadratic segment stroke. (CanvasBezierSegment): Paint a bezier segment stroke. (CanvasArcToSegment): Paint an arcTo stroke. (CanvasArcSegment): Paint an arc stroke. (CanvasRect): Paint a rect. (CanvasRectFill): Paint a filled rect. (CanvasPathBenchmark): (CanvasPathBenchmark.prototype.createStage): Look for the pathType and create the stage using the right paint object. (window.benchmarkClient.create): git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190912 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- diff --git a/PerformanceTests/Animometer/runner/resources/tests.js b/PerformanceTests/Animometer/runner/resources/tests.js index 5b4f02c..64305d7 100644 --- a/PerformanceTests/Animometer/runner/resources/tests.js +++ b/PerformanceTests/Animometer/runner/resources/tests.js @@ -136,6 +136,43 @@ Suites.push(new Suite("SVG suite", ] )); +Suites.push(new Suite("Basic canvas path suite", + [ + { + url: "simple/simple-canvas-paths.html?pathType=quadratic", + name: "Canvas quadratic segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=bezier", + name: "Canvas bezier segments" + }, + { + url: "simple/simple-canvas-paths.html?&pathType=arcTo", + name: "Canvas arcTo segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=arc", + name: "Canvas arc segments" + }, + { + url: "simple/simple-canvas-paths.html?pathType=rect", + name: "Canvas rects" + }, + { + url: "simple/simple-canvas-paths.html?&pathType=arcToFill", + name: "Canvas arcTo segments, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=arcFill", + name: "Canvas arc segments, fill" + }, + { + url: "simple/simple-canvas-paths.html?pathType=rectFill", + name: "Canvas rects, fill" + } + ] +)); + Suites.push(new Suite("Complex examples", [ { diff --git a/PerformanceTests/Animometer/tests/resources/stage.js b/PerformanceTests/Animometer/tests/resources/stage.js index 6d6ed24..4763619 100644 --- a/PerformanceTests/Animometer/tests/resources/stage.js +++ b/PerformanceTests/Animometer/tests/resources/stage.js @@ -55,9 +55,14 @@ Stage.prototype = return (Math.random() * (max - min)) + min; }, + randomBool: function() + { + return !!Math.round(this.random(0, 1)); + }, + randomInt: function(min, max) { - return Math.floor(this.random(min, max)); + return Math.round(this.random(min, max)); }, randomPosition: function(maxPosition) diff --git a/PerformanceTests/Animometer/tests/simple/resources/simple-canvas-paths.js b/PerformanceTests/Animometer/tests/simple/resources/simple-canvas-paths.js new file mode 100644 index 0000000..79c85d1 --- /dev/null +++ b/PerformanceTests/Animometer/tests/simple/resources/simple-canvas-paths.js @@ -0,0 +1,138 @@ +// === PAINT OBJECTS === + +function CanvasQuadraticSegment(stage) { + var maxSize = stage.randomInt(20, 200); + var toCenter = stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._color = stage.randomColor(); + this._lineWidth = stage.randomInt(1, 50); +}; +CanvasQuadraticSegment.prototype.draw = function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.quadraticCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y); + context.stroke(); +}; + +function CanvasBezierSegment(stage) { + var maxSize = stage.randomInt(20, 200); + var toCenter = stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point4 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._color = stage.randomColor(); + this._lineWidth = stage.randomInt(1, 50); +}; +CanvasBezierSegment.prototype.draw = function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._point4.x, this._point4.y); + context.stroke(); +}; + +function CanvasArcToSegment(stage) { + var maxSize = stage.randomInt(20, 200); + var toCenter = stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point1 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point2 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._point3 = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._radius = stage.randomInt(20, 200); + this._color = stage.randomColor(); + this._lineWidth = stage.randomInt(1, 50); +}; +CanvasArcToSegment.prototype.draw = function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.moveTo(this._point1.x, this._point1.y); + context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius); + context.stroke(); +}; + +function CanvasArcSegment(stage) { + var maxSize = stage.randomInt(20, 200); + var toCenter = stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2)); + + this._point = stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter); + this._radius = stage.randomInt(20, 200); + this._startAngle = stage.randomAngle(); + this._endAngle = stage.randomAngle(); + this._counterclockwise = stage.randomBool(); + this._color = stage.randomColor(); + this._lineWidth = stage.randomInt(1, 50); +}; +CanvasArcSegment.prototype.draw = function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise); + context.stroke(); +}; + +function CanvasRect(stage) { + this._width = stage.randomInt(20, 200); + this._height = stage.randomInt(20, 200); + this._point = stage.randomPosition(stage.size).subtract(new Point(this._width/2, this._height/2)); + this._color = stage.randomColor(); + this._lineWidth = stage.randomInt(1, 20); +} +CanvasRect.prototype.draw = function(context) { + context.strokeStyle = this._color; + context.lineWidth = this._lineWidth; + context.beginPath(); + context.rect(this._point.x, this._point.y, this._width, this._height); + context.stroke(); +}; + +function CanvasRectFill(stage) { + CanvasRect.call(this, stage); +} +CanvasRectFill.prototype.draw = function(context) { + context.fillStyle = this._color; + context.beginPath(); + context.rect(this._point.x, this._point.y, this._width, this._height); + context.fill(); +}; + +// === BENCHMARK === + +function CanvasPathBenchmark(suite, test, options, recordTable, progressBar) { + SimpleCanvasBenchmark.call(this, suite, test, options, recordTable, progressBar); +} +CanvasPathBenchmark.prototype = Object.create(SimpleCanvasBenchmark.prototype); +CanvasPathBenchmark.prototype.constructor = CanvasPathBenchmark; +CanvasPathBenchmark.prototype.createStage = function(element) +{ + switch (this._options["pathType"]) { + case "quadratic": + return new SimpleCanvasStage(element, this._options, CanvasQuadraticSegment); + case "bezier": + return new SimpleCanvasStage(element, this._options, CanvasBezierSegment); + 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 "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); + } +} + +window.benchmarkClient.create = function(suite, test, options, recordTable, progressBar) { + return new CanvasPathBenchmark(suite, test, options, recordTable, progressBar); +} diff --git a/PerformanceTests/Animometer/tests/simple/resources/simple-canvas.js b/PerformanceTests/Animometer/tests/simple/resources/simple-canvas.js new file mode 100644 index 0000000..9260a4f --- /dev/null +++ b/PerformanceTests/Animometer/tests/simple/resources/simple-canvas.js @@ -0,0 +1,62 @@ + +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 (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(-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) +{ + StageAnimator.call(this, benchmark); + 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); +} + + +function SimpleCanvasBenchmark(suite, test, options, recordTable, progressBar) { + options["gain"] = 6; + options["addLimit"] = 100; + options["removeLimit"] = 1000; + StageBenchmark.call(this, suite, test, options, recordTable, progressBar); +} +SimpleCanvasBenchmark.prototype = Object.create(StageBenchmark.prototype); +SimpleCanvasBenchmark.prototype.constructor = SimpleCanvasBenchmark; +SimpleCanvasBenchmark.prototype.createAnimator = function() { + return new SimpleCanvasAnimator(this); +} + diff --git a/PerformanceTests/Animometer/tests/simple/simple-canvas-paths.html b/PerformanceTests/Animometer/tests/simple/simple-canvas-paths.html new file mode 100644 index 0000000..bf61846 --- /dev/null +++ b/PerformanceTests/Animometer/tests/simple/simple-canvas-paths.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/PerformanceTests/ChangeLog b/PerformanceTests/ChangeLog index ef1d64c..442a386 100644 --- a/PerformanceTests/ChangeLog +++ b/PerformanceTests/ChangeLog @@ -1,5 +1,52 @@ 2015-10-12 Jon Lee + Add basic canvas tests + https://bugs.webkit.org/show_bug.cgi?id=150066 + rdar://problem/23081143 + + Reviewed by Dean Jackson. + + This adds a new test suite that will cover all of the path-based canvas calls. + The patch will be divided up to cover tests with similar techniques. + + The simplest version uses a SimpleCanvasStage. + + * Animometer/runner/resources/tests.js: Add tests for quadratic, bezier, arcTo, + arc, and rect segments. Also include arcTo, arc, and rect fills. + * Animometer/tests/resources/stage.js: + (Stage.prototype.randomBool): Added for counterclockwise property for arc segments. + (Stage.prototype.randomInt): Fix how values are rounded, used by randomBool. It should + round instead of flooring everything. + * Animometer/tests/simple/resources/simple-canvas.js: Added. Defines common classes + used by all simple canvas tests. The page reads best bottom to top. + (SimpleCanvasStage): Basic stage. Pass a canvasObject which will be used to create new + objects as needed in tune(). + (SimpleCanvasStage.prototype.tune): Modeled on other tests. Adds and removed objects + as specified by the provided |count|. + (SimpleCanvasStage.prototype.animate): Iterate over all the objects and ask them to draw. + There is no "animating" of the objects; they will just paint statically on the canvas. + (SimpleCanvasAnimator): Basic animator clears the canvas prior to painting. + (SimpleCanvasBenchmark): Hard-code the feedback loop parameters instead of including + them in the query parameters to the test URLs. + (SimpleCanvasBenchmark.prototype.createAnimator): + * Animometer/tests/simple/simple-canvas-paths.html: Added. + + * Animometer/tests/simple/resources/simple-canvas-paths.js: Added. There is no "animating" + of these objects--they just paint statically on the canvas. + (CanvasQuadraticSegment): Paint a quadratic segment stroke. + (CanvasBezierSegment): Paint a bezier segment stroke. + (CanvasArcToSegment): Paint an arcTo stroke. + (CanvasArcSegment): Paint an arc stroke. + (CanvasRect): Paint a rect. + (CanvasRectFill): Paint a filled rect. + + (CanvasPathBenchmark): + (CanvasPathBenchmark.prototype.createStage): Look for the pathType and create the + stage using the right paint object. + (window.benchmarkClient.create): + +2015-10-12 Jon Lee + Refactor tune() to pass in an integer-based count https://bugs.webkit.org/show_bug.cgi?id=150060