Restructure Canvas replay classes
This commit is contained in:
@@ -0,0 +1,381 @@
|
||||
goog.provide('ol.render.canvas.PolygonReplay');
|
||||
|
||||
goog.require('ol');
|
||||
goog.require('ol.color');
|
||||
goog.require('ol.colorlike');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
goog.require('ol.render.canvas');
|
||||
goog.require('ol.render.canvas.Instruction');
|
||||
goog.require('ol.render.canvas.Replay');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.render.canvas.Replay}
|
||||
* @param {number} tolerance Tolerance.
|
||||
* @param {ol.Extent} maxExtent Maximum extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {boolean} overlaps The replay can have overlapping geometries.
|
||||
* @struct
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay = function(tolerance, maxExtent, resolution, overlaps) {
|
||||
|
||||
ol.render.canvas.Replay.call(this, tolerance, maxExtent, resolution, overlaps);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
this.bufferedMaxExtent_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{currentFillStyle: (ol.ColorLike|undefined),
|
||||
* currentStrokeStyle: (string|undefined),
|
||||
* currentLineCap: (string|undefined),
|
||||
* currentLineDash: Array.<number>,
|
||||
* currentLineJoin: (string|undefined),
|
||||
* currentLineWidth: (number|undefined),
|
||||
* currentMiterLimit: (number|undefined),
|
||||
* fillStyle: (ol.ColorLike|undefined),
|
||||
* strokeStyle: (string|undefined),
|
||||
* lineCap: (string|undefined),
|
||||
* lineDash: Array.<number>,
|
||||
* lineJoin: (string|undefined),
|
||||
* lineWidth: (number|undefined),
|
||||
* miterLimit: (number|undefined)}|null}
|
||||
*/
|
||||
this.state_ = {
|
||||
currentFillStyle: undefined,
|
||||
currentStrokeStyle: undefined,
|
||||
currentLineCap: undefined,
|
||||
currentLineDash: null,
|
||||
currentLineJoin: undefined,
|
||||
currentLineWidth: undefined,
|
||||
currentMiterLimit: undefined,
|
||||
fillStyle: undefined,
|
||||
strokeStyle: undefined,
|
||||
lineCap: undefined,
|
||||
lineDash: null,
|
||||
lineJoin: undefined,
|
||||
lineWidth: undefined,
|
||||
miterLimit: undefined
|
||||
};
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.canvas.PolygonReplay, ol.render.canvas.Replay);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @private
|
||||
* @return {number} End.
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) {
|
||||
var state = this.state_;
|
||||
var fill = state.fillStyle !== undefined;
|
||||
var stroke = state.strokeStyle != undefined;
|
||||
var numEnds = ends.length;
|
||||
if (!fill && !stroke) {
|
||||
return ends[numEnds - 1];
|
||||
}
|
||||
var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
|
||||
this.instructions.push(beginPathInstruction);
|
||||
this.hitDetectionInstructions.push(beginPathInstruction);
|
||||
for (var i = 0; i < numEnds; ++i) {
|
||||
var end = ends[i];
|
||||
var myBegin = this.coordinates.length;
|
||||
var myEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride,
|
||||
// Performance optimization: only close the ring when we do not have a
|
||||
// stroke. Otherwise closePath() will take care of that.
|
||||
!stroke);
|
||||
var moveToLineToInstruction =
|
||||
[ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
|
||||
this.instructions.push(moveToLineToInstruction);
|
||||
this.hitDetectionInstructions.push(moveToLineToInstruction);
|
||||
if (stroke) {
|
||||
// Performance optimization: only call closePath() when we have a stroke.
|
||||
// Otherwise the ring is closed already (see appendFlatCoordinates above).
|
||||
var closePathInstruction = [ol.render.canvas.Instruction.CLOSE_PATH];
|
||||
this.instructions.push(closePathInstruction);
|
||||
this.hitDetectionInstructions.push(closePathInstruction);
|
||||
}
|
||||
offset = end;
|
||||
}
|
||||
var fillInstruction = [ol.render.canvas.Instruction.FILL];
|
||||
this.hitDetectionInstructions.push(fillInstruction);
|
||||
if (fill) {
|
||||
this.instructions.push(fillInstruction);
|
||||
}
|
||||
if (stroke) {
|
||||
ol.DEBUG && console.assert(state.lineWidth !== undefined,
|
||||
'state.lineWidth should be defined');
|
||||
var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
|
||||
this.instructions.push(strokeInstruction);
|
||||
this.hitDetectionInstructions.push(strokeInstruction);
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
|
||||
var state = this.state_;
|
||||
ol.DEBUG && console.assert(state, 'state should not be null');
|
||||
var fillStyle = state.fillStyle;
|
||||
var strokeStyle = state.strokeStyle;
|
||||
if (fillStyle === undefined && strokeStyle === undefined) {
|
||||
return;
|
||||
}
|
||||
if (strokeStyle !== undefined) {
|
||||
ol.DEBUG && console.assert(state.lineWidth !== undefined,
|
||||
'state.lineWidth should be defined');
|
||||
}
|
||||
this.setFillStrokeStyles_();
|
||||
this.beginGeometry(circleGeometry, feature);
|
||||
// always fill the circle for hit detection
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_FILL_STYLE,
|
||||
ol.color.asString(ol.render.canvas.defaultFillStyle)]);
|
||||
if (state.strokeStyle !== undefined) {
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_STROKE_STYLE,
|
||||
state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
|
||||
state.miterLimit, state.lineDash]);
|
||||
}
|
||||
var flatCoordinates = circleGeometry.getFlatCoordinates();
|
||||
var stride = circleGeometry.getStride();
|
||||
var myBegin = this.coordinates.length;
|
||||
this.appendFlatCoordinates(
|
||||
flatCoordinates, 0, flatCoordinates.length, stride, false);
|
||||
var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
|
||||
var circleInstruction = [ol.render.canvas.Instruction.CIRCLE, myBegin];
|
||||
this.instructions.push(beginPathInstruction, circleInstruction);
|
||||
this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
|
||||
var fillInstruction = [ol.render.canvas.Instruction.FILL];
|
||||
this.hitDetectionInstructions.push(fillInstruction);
|
||||
if (state.fillStyle !== undefined) {
|
||||
this.instructions.push(fillInstruction);
|
||||
}
|
||||
if (state.strokeStyle !== undefined) {
|
||||
ol.DEBUG && console.assert(state.lineWidth !== undefined,
|
||||
'state.lineWidth should be defined');
|
||||
var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
|
||||
this.instructions.push(strokeInstruction);
|
||||
this.hitDetectionInstructions.push(strokeInstruction);
|
||||
}
|
||||
this.endGeometry(circleGeometry, feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
|
||||
var state = this.state_;
|
||||
ol.DEBUG && console.assert(state, 'state should not be null');
|
||||
var fillStyle = state.fillStyle;
|
||||
var strokeStyle = state.strokeStyle;
|
||||
if (fillStyle === undefined && strokeStyle === undefined) {
|
||||
return;
|
||||
}
|
||||
if (strokeStyle !== undefined) {
|
||||
ol.DEBUG && console.assert(state.lineWidth !== undefined,
|
||||
'state.lineWidth should be defined');
|
||||
}
|
||||
this.setFillStrokeStyles_();
|
||||
this.beginGeometry(polygonGeometry, feature);
|
||||
// always fill the polygon for hit detection
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_FILL_STYLE,
|
||||
ol.color.asString(ol.render.canvas.defaultFillStyle)]);
|
||||
if (state.strokeStyle !== undefined) {
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_STROKE_STYLE,
|
||||
state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
|
||||
state.miterLimit, state.lineDash]);
|
||||
}
|
||||
var ends = polygonGeometry.getEnds();
|
||||
var flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
|
||||
var stride = polygonGeometry.getStride();
|
||||
this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
|
||||
this.endGeometry(polygonGeometry, feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
|
||||
var state = this.state_;
|
||||
ol.DEBUG && console.assert(state, 'state should not be null');
|
||||
var fillStyle = state.fillStyle;
|
||||
var strokeStyle = state.strokeStyle;
|
||||
if (fillStyle === undefined && strokeStyle === undefined) {
|
||||
return;
|
||||
}
|
||||
if (strokeStyle !== undefined) {
|
||||
ol.DEBUG && console.assert(state.lineWidth !== undefined,
|
||||
'state.lineWidth should be defined');
|
||||
}
|
||||
this.setFillStrokeStyles_();
|
||||
this.beginGeometry(multiPolygonGeometry, feature);
|
||||
// always fill the multi-polygon for hit detection
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_FILL_STYLE,
|
||||
ol.color.asString(ol.render.canvas.defaultFillStyle)]);
|
||||
if (state.strokeStyle !== undefined) {
|
||||
this.hitDetectionInstructions.push(
|
||||
[ol.render.canvas.Instruction.SET_STROKE_STYLE,
|
||||
state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
|
||||
state.miterLimit, state.lineDash]);
|
||||
}
|
||||
var endss = multiPolygonGeometry.getEndss();
|
||||
var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
|
||||
var stride = multiPolygonGeometry.getStride();
|
||||
var offset = 0;
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
offset = this.drawFlatCoordinatess_(
|
||||
flatCoordinates, offset, endss[i], stride);
|
||||
}
|
||||
this.endGeometry(multiPolygonGeometry, feature);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.finish = function() {
|
||||
ol.DEBUG && console.assert(this.state_, 'this.state_ should not be null');
|
||||
this.reverseHitDetectionInstructions();
|
||||
this.state_ = null;
|
||||
// We want to preserve topology when drawing polygons. Polygons are
|
||||
// simplified using quantization and point elimination. However, we might
|
||||
// have received a mix of quantized and non-quantized geometries, so ensure
|
||||
// that all are quantized by quantizing all coordinates in the batch.
|
||||
var tolerance = this.tolerance;
|
||||
if (tolerance !== 0) {
|
||||
var coordinates = this.coordinates;
|
||||
var i, ii;
|
||||
for (i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
coordinates[i] = ol.geom.flat.simplify.snap(coordinates[i], tolerance);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.getBufferedMaxExtent = function() {
|
||||
if (!this.bufferedMaxExtent_) {
|
||||
this.bufferedMaxExtent_ = ol.extent.clone(this.maxExtent);
|
||||
if (this.maxLineWidth > 0) {
|
||||
var width = this.resolution * (this.maxLineWidth + 1) / 2;
|
||||
ol.extent.buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
|
||||
}
|
||||
}
|
||||
return this.bufferedMaxExtent_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
|
||||
ol.DEBUG && console.assert(this.state_, 'this.state_ should not be null');
|
||||
ol.DEBUG && console.assert(fillStyle || strokeStyle,
|
||||
'fillStyle or strokeStyle should not be null');
|
||||
var state = this.state_;
|
||||
if (fillStyle) {
|
||||
var fillStyleColor = fillStyle.getColor();
|
||||
state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ?
|
||||
fillStyleColor : ol.render.canvas.defaultFillStyle);
|
||||
} else {
|
||||
state.fillStyle = undefined;
|
||||
}
|
||||
if (strokeStyle) {
|
||||
var strokeStyleColor = strokeStyle.getColor();
|
||||
state.strokeStyle = ol.color.asString(strokeStyleColor ?
|
||||
strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
||||
var strokeStyleLineCap = strokeStyle.getLineCap();
|
||||
state.lineCap = strokeStyleLineCap !== undefined ?
|
||||
strokeStyleLineCap : ol.render.canvas.defaultLineCap;
|
||||
var strokeStyleLineDash = strokeStyle.getLineDash();
|
||||
state.lineDash = strokeStyleLineDash ?
|
||||
strokeStyleLineDash.slice() : ol.render.canvas.defaultLineDash;
|
||||
var strokeStyleLineJoin = strokeStyle.getLineJoin();
|
||||
state.lineJoin = strokeStyleLineJoin !== undefined ?
|
||||
strokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
|
||||
var strokeStyleWidth = strokeStyle.getWidth();
|
||||
state.lineWidth = strokeStyleWidth !== undefined ?
|
||||
strokeStyleWidth : ol.render.canvas.defaultLineWidth;
|
||||
var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
|
||||
state.miterLimit = strokeStyleMiterLimit !== undefined ?
|
||||
strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
|
||||
|
||||
if (state.lineWidth > this.maxLineWidth) {
|
||||
this.maxLineWidth = state.lineWidth;
|
||||
// invalidate the buffered max extent cache
|
||||
this.bufferedMaxExtent_ = null;
|
||||
}
|
||||
} else {
|
||||
state.strokeStyle = undefined;
|
||||
state.lineCap = undefined;
|
||||
state.lineDash = null;
|
||||
state.lineJoin = undefined;
|
||||
state.lineWidth = undefined;
|
||||
state.miterLimit = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function() {
|
||||
var state = this.state_;
|
||||
var fillStyle = state.fillStyle;
|
||||
var strokeStyle = state.strokeStyle;
|
||||
var lineCap = state.lineCap;
|
||||
var lineDash = state.lineDash;
|
||||
var lineJoin = state.lineJoin;
|
||||
var lineWidth = state.lineWidth;
|
||||
var miterLimit = state.miterLimit;
|
||||
if (fillStyle !== undefined && state.currentFillStyle != fillStyle) {
|
||||
this.instructions.push(
|
||||
[ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle]);
|
||||
state.currentFillStyle = state.fillStyle;
|
||||
}
|
||||
if (strokeStyle !== undefined) {
|
||||
ol.DEBUG && console.assert(lineCap !== undefined, 'lineCap should be defined');
|
||||
ol.DEBUG && console.assert(lineDash, 'lineDash should not be null');
|
||||
ol.DEBUG && console.assert(lineJoin !== undefined, 'lineJoin should be defined');
|
||||
ol.DEBUG && console.assert(lineWidth !== undefined, 'lineWidth should be defined');
|
||||
ol.DEBUG && console.assert(miterLimit !== undefined,
|
||||
'miterLimit should be defined');
|
||||
if (state.currentStrokeStyle != strokeStyle ||
|
||||
state.currentLineCap != lineCap ||
|
||||
state.currentLineDash != lineDash ||
|
||||
state.currentLineJoin != lineJoin ||
|
||||
state.currentLineWidth != lineWidth ||
|
||||
state.currentMiterLimit != miterLimit) {
|
||||
this.instructions.push(
|
||||
[ol.render.canvas.Instruction.SET_STROKE_STYLE,
|
||||
strokeStyle, lineWidth, lineCap, lineJoin, miterLimit, lineDash]);
|
||||
state.currentStrokeStyle = strokeStyle;
|
||||
state.currentLineCap = lineCap;
|
||||
state.currentLineDash = lineDash;
|
||||
state.currentLineJoin = lineJoin;
|
||||
state.currentLineWidth = lineWidth;
|
||||
state.currentMiterLimit = miterLimit;
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user