diff --git a/src/ol/replay/canvas/canvasbatchgroup.js b/src/ol/replay/canvas/canvasbatchgroup.js new file mode 100644 index 0000000000..776cf32000 --- /dev/null +++ b/src/ol/replay/canvas/canvasbatchgroup.js @@ -0,0 +1,220 @@ +// FIXME store coordinates in batchgroup? +// FIXME flattened coordinates +// FIXME per-batch extent tests + +goog.provide('ol.replay.canvas.BatchGroup'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.functions'); +goog.require('goog.object'); +goog.require('ol.replay'); +goog.require('ol.replay.IBatch'); +goog.require('ol.replay.IBatchGroup'); + + +/** + * @enum {number} + */ +ol.replay.canvas.InstructionType = { + DRAW_LINE_STRING_GEOMETRY: 0, + SET_STROKE_STYLE: 1 +}; + + +/** + * @typedef {{argument: ?, + * type: ol.replay.canvas.InstructionType}} + */ +ol.replay.canvas.Instruction; + + + +/** + * @constructor + * @implements {ol.replay.IBatch} + */ +ol.replay.canvas.Batch = function() { + + /** + * @private + * @type {Array.} + */ + this.instructions_ = []; + + /** + * @private + * @type {Array.} + */ + this.coordinates_ = []; + + /** + * @private + * @type {Array.} + */ + this.pixelCoordinates_ = []; + +}; + + +/** + * @param {CanvasRenderingContext2D} context Context. + * @param {goog.vec.Mat4.AnyType} transform Transform. + */ +ol.replay.canvas.Batch.prototype.draw = function(context, transform) { + var pixelCoordinates = ol.replay.transformCoordinates( + this.coordinates_, transform, this.pixelCoordinates_); + this.pixelCoordinates_ = pixelCoordinates; // FIXME ? + var begunPath = false; + var fillPending = false; + var strokePending = false; + var flushPath = function() { + if (strokePending || fillPending) { + if (strokePending) { + context.stroke(); + strokePending = false; + } + if (fillPending) { + context.fill(); + fillPending = false; + } + context.beginPath(); + begunPath = true; + } + }; + var instructions = this.instructions_; + var i = 0; + var j, jj; + for (j = 0, jj = instructions.length; j < jj; ++j) { + var instruction = instructions[j]; + if (instruction.type == + ol.replay.canvas.InstructionType.DRAW_LINE_STRING_GEOMETRY) { + if (!begunPath) { + context.beginPath(); + begunPath = true; + } + context.moveTo(pixelCoordinates[i], pixelCoordinates[i + 1]); + goog.asserts.assert(goog.isNumber(instruction.argument)); + var ii = /** @type {number} */ (instruction.argument); + for (i += 2; i < ii; i += 2) { + context.lineTo(pixelCoordinates[i], pixelCoordinates[i + 1]); + } + strokePending = true; + } else if (instruction.type == + ol.replay.canvas.InstructionType.SET_STROKE_STYLE) { + flushPath(); + goog.asserts.assert(goog.isObject(instruction.argument)); + var strokeStyle = /** @type {ol.style.Stroke} */ (instruction.argument); + context.strokeStyle = strokeStyle.color; + context.lineWidth = strokeStyle.width; + } + } + flushPath(); + goog.asserts.assert(i == pixelCoordinates.length); +}; + + +/** + * @inheritDoc + */ +ol.replay.canvas.Batch.prototype.drawLineStringGeometry = + function(lineStringGeometry) { + var coordinates = this.coordinates_; + var lineStringCoordinates = lineStringGeometry.getCoordinates(); + var i = coordinates.length; + var j, jj; + for (j = 0, jj = lineStringCoordinates.length; j < jj; ++j) { + coordinates[i++] = lineStringCoordinates[j][0]; + coordinates[i++] = lineStringCoordinates[j][1]; + } + this.instructions_.push({ + type: ol.replay.canvas.InstructionType.DRAW_LINE_STRING_GEOMETRY, + argument: i + }); +}; + + +/** + * @inheritDoc + */ +ol.replay.canvas.Batch.prototype.setStrokeStyle = function(strokeStyle) { + this.instructions_.push({ + type: ol.replay.canvas.InstructionType.SET_STROKE_STYLE, + argument: strokeStyle + }); +}; + + + +/** + * @constructor + * @implements {ol.replay.IBatchGroup} + */ +ol.replay.canvas.BatchGroup = function() { + + /** + * @private + * @type {Object.>} + */ + this.batchesByZIndex_ = {}; + +}; + + +/** + * @param {CanvasRenderingContext2D} context Context. + * @param {goog.vec.Mat4.AnyType} transform Transform. + */ +ol.replay.canvas.BatchGroup.prototype.draw = function(context, transform) { + window.console.log('drawing batch'); + /** @type {Array.} */ + var zs = goog.array.map(goog.object.getKeys(this.batchesByZIndex_), Number); + goog.array.sort(zs); + var i, ii; + for (i = 0, ii = zs.length; i < ii; ++i) { + var batches = this.batchesByZIndex_[zs[i].toString()]; + var batchType; + for (batchType in batches) { + var batch = batches[batchType]; + batch.draw(context, transform); + } + } +}; + + +/** + * @inheritDoc + */ +ol.replay.canvas.BatchGroup.prototype.getBatch = function(zIndex, batchType) { + var zIndexKey = zIndex.toString(); + var batches = this.batchesByZIndex_[zIndexKey]; + if (!goog.isDef(batches)) { + batches = {}; + this.batchesByZIndex_[zIndexKey] = batches; + } + var batch = batches[batchType]; + if (!goog.isDef(batch)) { + var constructor = ol.replay.canvas.BATCH_CONSTRUCTORS_[batchType]; + goog.asserts.assert(goog.isDef(constructor)); + batch = new constructor(); + batches[batchType] = batch; + } + return batch; +}; + + +/** + * @inheritDoc + */ +ol.replay.canvas.BatchGroup.prototype.isEmpty = goog.functions.FALSE; // FIXME + + +/** + * @const + * @private + * @type {Object.} + */ +ol.replay.canvas.BATCH_CONSTRUCTORS_ = { + 'strokeLine': ol.replay.canvas.Batch +};