Merge pull request #6082 from ahocevar/unified-canvas-rendering

Unified canvas rendering
This commit is contained in:
Andreas Hocevar
2016-12-06 08:59:40 +01:00
committed by GitHub
19 changed files with 400 additions and 514 deletions

View File

@@ -149,6 +149,23 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
};
/**
* @param {ol.Transform} transform Transform.
* @return {Array.<number>} Clip coordinates.
*/
ol.render.canvas.ReplayGroup.prototype.getClipCoords = function(transform) {
var maxExtent = this.maxExtent_;
var minX = maxExtent[0];
var minY = maxExtent[1];
var maxX = maxExtent[2];
var maxY = maxExtent[3];
var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
ol.geom.flat.transform.transform2D(
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
return flatClipCoords;
};
/**
* @inheritDoc
*/
@@ -200,14 +217,7 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, pixelRatio,
// setup clipping so that the parts of over-simplified geometries are not
// visible outside the current extent when panning
var maxExtent = this.maxExtent_;
var minX = maxExtent[0];
var minY = maxExtent[1];
var maxX = maxExtent[2];
var maxY = maxExtent[3];
var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
ol.geom.flat.transform.transform2D(
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
var flatClipCoords = this.getClipCoords(transform);
context.save();
context.beginPath();
context.moveTo(flatClipCoords[0], flatClipCoords[1]);

View File

@@ -34,9 +34,9 @@ ol.renderer.canvas.ImageLayer = function(imageLayer) {
/**
* @private
* @type {?ol.Transform}
* @type {ol.Transform}
*/
this.imageTransformInv_ = null;
this.coordinateToCanvasPixelTransform_ = ol.transform.create();
/**
* @private
@@ -70,7 +70,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate = function(co
/**
* @param {ol.Pixel} pixel Pixel.
* @param {ol.Coordinate} coordinate Coordinate.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
@@ -78,7 +78,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate = function(co
* @return {T|undefined} Callback result.
* @template S,T,U
*/
ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
if (!this.getImage()) {
return undefined;
}
@@ -86,8 +86,6 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, fr
if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
// for ImageVector sources use the original hit-detection logic,
// so that for example also transparent polygons are detected
var coordinate = ol.transform.apply(
frameState.pixelToCoordinateTransform, pixel.slice());
var hasFeature = this.forEachFeatureAtCoordinate(
coordinate, frameState, ol.functions.TRUE, this);
@@ -97,13 +95,8 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, fr
return undefined;
}
} else {
// for all other image sources directly check the image
if (!this.imageTransformInv_) {
this.imageTransformInv_ = ol.transform.invert(this.imageTransform_.slice());
}
var pixelOnCanvas =
this.getPixelOnCanvas(pixel, this.imageTransformInv_);
var pixelOnCanvas = ol.transform.apply(
this.coordinateToCanvasPixelTransform_, coordinate.slice());
if (!this.hitCanvasContext_) {
this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
@@ -145,6 +138,7 @@ ol.renderer.canvas.ImageLayer.prototype.getImageTransform = function() {
ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, layerState) {
var pixelRatio = frameState.pixelRatio;
var size = frameState.size;
var viewState = frameState.viewState;
var viewCenter = viewState.center;
var viewResolution = viewState.resolution;
@@ -197,7 +191,11 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, laye
ol.transform.translate(transform,
imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
this.imageTransformInv_ = null;
ol.transform.compose(ol.transform.reset(this.coordinateToCanvasPixelTransform_),
pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
pixelRatio / viewResolution, -pixelRatio / viewResolution,
0,
-viewCenter[0], -viewCenter[1]);
this.updateAttributions(frameState.attributions, image.getAttributions());
this.updateLogos(frameState, imageSource);
}

View File

@@ -2,6 +2,7 @@ goog.provide('ol.renderer.canvas.Layer');
goog.require('ol');
goog.require('ol.extent');
goog.require('ol.functions');
goog.require('ol.render.Event');
goog.require('ol.render.canvas');
goog.require('ol.render.canvas.Immediate');
@@ -68,7 +69,7 @@ ol.renderer.canvas.Layer.prototype.clip = function(context, frameState, extent)
*/
ol.renderer.canvas.Layer.prototype.composeFrame = function(frameState, layerState, context) {
this.dispatchPreComposeEvent(context, frameState);
this.preCompose(context, frameState);
var image = this.getImage();
if (image) {
@@ -102,8 +103,7 @@ ol.renderer.canvas.Layer.prototype.composeFrame = function(frameState, layerStat
}
}
this.dispatchPostComposeEvent(context, frameState);
this.postCompose(context, frameState, layerState);
};
@@ -137,10 +137,11 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ = function(type, contex
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @param {ol.Transform=} opt_transform Transform.
* @protected
*/
ol.renderer.canvas.Layer.prototype.dispatchPostComposeEvent = function(context, frameState, opt_transform) {
ol.renderer.canvas.Layer.prototype.postCompose = function(context, frameState, layerState, opt_transform) {
this.dispatchComposeEvent_(ol.render.Event.Type.POSTCOMPOSE, context,
frameState, opt_transform);
};
@@ -152,7 +153,7 @@ ol.renderer.canvas.Layer.prototype.dispatchPostComposeEvent = function(context,
* @param {ol.Transform=} opt_transform Transform.
* @protected
*/
ol.renderer.canvas.Layer.prototype.dispatchPreComposeEvent = function(context, frameState, opt_transform) {
ol.renderer.canvas.Layer.prototype.preCompose = function(context, frameState, opt_transform) {
this.dispatchComposeEvent_(ol.render.Event.Type.PRECOMPOSE, context,
frameState, opt_transform);
};
@@ -214,12 +215,21 @@ ol.renderer.canvas.Layer.prototype.prepareFrame = function(frameState, layerStat
/**
* @param {ol.Pixel} pixelOnMap Pixel.
* @param {ol.Transform} imageTransformInv The transformation matrix
* to convert from a map pixel to a canvas pixel.
* @return {ol.Pixel} The pixel.
* @protected
* @param {ol.Coordinate} coordinate Coordinate.
* @param {olx.FrameState} frameState Frame state.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T
*/
ol.renderer.canvas.Layer.prototype.getPixelOnCanvas = function(pixelOnMap, imageTransformInv) {
return ol.transform.apply(imageTransformInv, pixelOnMap.slice());
ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
var hasFeature = this.forEachFeatureAtCoordinate(
coordinate, frameState, ol.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.getLayer(), null);
} else {
return undefined;
}
};

View File

@@ -200,3 +200,36 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
this.scheduleRemoveUnusedLayerRenderers(frameState);
this.scheduleExpireIconCache(frameState);
};
/**
* @inheritDoc
*/
ol.renderer.canvas.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
layerFilter, thisArg2) {
var result;
var viewState = frameState.viewState;
var viewResolution = viewState.resolution;
var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length;
var coordinate = ol.transform.apply(
frameState.pixelToCoordinateTransform, pixel.slice());
var i;
for (i = numLayers - 1; i >= 0; --i) {
var layerState = layerStates[i];
var layer = layerState.layer;
if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
layerFilter.call(thisArg2, layer)) {
var layerRenderer = /** @type {ol.renderer.canvas.Layer} */ (this.getLayerRenderer(layer));
result = layerRenderer.forEachLayerAtCoordinate(
coordinate, frameState, callback, thisArg);
if (result) {
return result;
}
}
}
return undefined;
};

View File

@@ -9,8 +9,6 @@ goog.require('ol.Tile');
goog.require('ol.array');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.render.canvas');
goog.require('ol.render.Event');
goog.require('ol.renderer.canvas.Layer');
@@ -29,9 +27,27 @@ ol.renderer.canvas.TileLayer = function(tileLayer) {
*/
this.context = ol.dom.createCanvasContext2D();
/**
* @private
* @type {ol.Extent}
*/
this.renderedExtent_ = null;
/**
* @private
* @type {number}
*/
this.renderedResolution_;
/**
* @private
* @type {number}
*/
this.renderedRevision_;
/**
* @protected
* @type {!Array.<ol.Tile|undefined>}
* @type {!Array.<ol.Tile>}
*/
this.renderedTiles = [];
@@ -47,12 +63,24 @@ ol.renderer.canvas.TileLayer = function(tileLayer) {
*/
this.tmpTileCoord_ = [0, 0, 0];
/**
* @private
* @type {ol.TileRange}
*/
this.tmpTileRange_ = new ol.TileRange(0, 0, 0, 0);
/**
* @private
* @type {ol.Transform}
*/
this.imageTransform_ = ol.transform.create();
/**
* @private
* @type {ol.Transform}
*/
this.coordinateToCanvasPixelTransform_ = ol.transform.create();
/**
* @protected
* @type {number}
@@ -66,29 +94,20 @@ ol.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
ol.renderer.canvas.TileLayer.prototype.composeFrame = function(
frameState, layerState, context) {
var transform = this.getTransform(frameState, 0);
this.dispatchPreComposeEvent(context, frameState, transform);
this.renderTileImages(context, frameState, layerState);
this.dispatchPostComposeEvent(context, frameState, transform);
};
/**
* @inheritDoc
*/
ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
frameState, layerState) {
ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layerState) {
var pixelRatio = frameState.pixelRatio;
var size = frameState.size;
var viewState = frameState.viewState;
var projection = viewState.projection;
var viewResolution = viewState.resolution;
var viewCenter = viewState.center;
var tileLayer = this.getLayer();
var tileSource = /** @type {ol.source.Tile} */ (tileLayer.getSource());
var sourceRevision = tileSource.getRevision();
var tileGrid = tileSource.getTileGridForProjection(projection);
var z = tileGrid.getZForResolution(viewState.resolution, this.zDirection);
var z = tileGrid.getZForResolution(viewResolution, this.zDirection);
var tileResolution = tileGrid.getResolution(z);
var extent = frameState.extent;
@@ -102,6 +121,9 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution);
var imageExtent = tileGrid.getTileRangeExtent(z, tileRange);
var tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio);
/**
* @type {Object.<number, Object.<string, ol.Tile>>}
@@ -113,35 +135,33 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
tileSource, projection, tilesToDrawByZ);
var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
var tmpExtent = this.tmpExtent;
var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
var childTileRange, fullyLoaded, tile, x, y;
var drawableTile = (
/**
* @param {!ol.Tile} tile Tile.
* @return {boolean} Tile is selected.
*/
function(tile) {
var tileState = tile.getState();
return tileState == ol.Tile.State.LOADED ||
tileState == ol.Tile.State.EMPTY ||
tileState == ol.Tile.State.ERROR && !useInterimTilesOnError;
});
var tmpTileRange = this.tmpTileRange_;
var newTiles = false;
var tile, x, y;
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
if (!drawableTile(tile)) {
var tileState = tile.getState();
var drawable = tileState == ol.Tile.State.LOADED ||
tileState == ol.Tile.State.EMPTY ||
tileState == ol.Tile.State.ERROR && !useInterimTilesOnError;
if (!drawable) {
tile = tile.getInterimTile();
}
if (drawableTile(tile)) {
tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
} else {
if (tileState == ol.Tile.State.LOADED) {
tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
if (!newTiles && this.renderedTiles.indexOf(tile) == -1) {
newTiles = true;
}
}
continue;
}
fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
var fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
if (!fullyLoaded) {
childTileRange = tileGrid.getTileCoordChildTileRange(
var childTileRange = tileGrid.getTileCoordChildTileRange(
tile.tileCoord, tmpTileRange, tmpExtent);
if (childTileRange) {
findLoadedTiles(z + 1, childTileRange);
@@ -151,35 +171,104 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
}
}
/** @type {Array.<number>} */
var zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
var renderables = this.renderedTiles;
renderables.length = 0;
var i, ii, currentZ, tileCoordKey, tilesToDraw;
for (i = 0, ii = zs.length; i < ii; ++i) {
currentZ = zs[i];
tilesToDraw = tilesToDrawByZ[currentZ];
for (tileCoordKey in tilesToDraw) {
tile = tilesToDraw[tileCoordKey];
if (tile.getState() == ol.Tile.State.LOADED) {
renderables.push(tile);
var hints = frameState.viewHints;
if (!(this.renderedResolution_ && Date.now() - frameState.time > 16 &&
(hints[ol.View.Hint.ANIMATING] || hints[ol.View.Hint.INTERACTING])) &&
(newTiles || !(this.renderedExtent_ &&
ol.extent.equals(this.renderedExtent_, imageExtent)) ||
this.renderedRevision_ != sourceRevision)) {
var tilePixelSize = tileSource.getTilePixelSize(z, pixelRatio, projection);
var width = tileRange.getWidth() * tilePixelSize[0];
var height = tileRange.getHeight() * tilePixelSize[0];
var context = this.context;
var canvas = context.canvas;
var opaque = tileSource.getOpaque(projection);
if (canvas.width != width || canvas.height != height) {
canvas.width = width;
canvas.height = height;
} else {
context.clearRect(0, 0, width, height);
}
this.renderedTiles.length = 0;
/** @type {Array.<number>} */
var zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
var currentResolution, currentScale, currentTilePixelSize, currentZ, i, ii;
var tileExtent, tileGutter, tilesToDraw, w, h;
for (i = 0, ii = zs.length; i < ii; ++i) {
currentZ = zs[i];
currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
currentResolution = tileGrid.getResolution(currentZ);
currentScale = currentResolution / tileResolution;
tileGutter = tilePixelRatio * tileSource.getGutter(projection);
tilesToDraw = tilesToDrawByZ[currentZ];
for (var tileCoordKey in tilesToDraw) {
tile = tilesToDraw[tileCoordKey];
tileExtent = tileGrid.getTileCoordExtent(tile.getTileCoord(), tmpExtent);
x = (tileExtent[0] - imageExtent[0]) / tileResolution * tilePixelRatio;
y = (imageExtent[3] - tileExtent[3]) / tileResolution * tilePixelRatio;
w = currentTilePixelSize[0] * currentScale;
h = currentTilePixelSize[1] * currentScale;
if (!opaque) {
context.clearRect(x, y, w, h);
}
this.drawTileImage(tile, frameState, layerState, x, y, w, h, tileGutter);
this.renderedTiles.push(tile);
}
}
this.renderedRevision_ = sourceRevision;
this.renderedResolution_ = tileResolution;
this.renderedExtent_ = imageExtent;
}
var scale = pixelRatio / tilePixelRatio * this.renderedResolution_ / viewResolution;
var transform = ol.transform.compose(this.imageTransform_,
pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
scale, scale,
0,
tilePixelRatio * (this.renderedExtent_[0] - viewCenter[0]) / this.renderedResolution_,
tilePixelRatio * (viewCenter[1] - this.renderedExtent_[3]) / this.renderedResolution_);
ol.transform.compose(this.coordinateToCanvasPixelTransform_,
pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
pixelRatio / viewResolution, -pixelRatio / viewResolution,
0,
-viewCenter[0], -viewCenter[1]);
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,
projection, extent, z, tileLayer.getPreload());
this.scheduleExpireCache(frameState, tileSource);
this.updateLogos(frameState, tileSource);
return true;
return this.renderedTiles.length > 0;
};
/**
* @param {ol.Pixel} pixel Pixel.
* @param {ol.Tile} tile Tile.
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @param {number} x Left of the tile.
* @param {number} y Top of the tile.
* @param {number} w Width of the tile.
* @param {number} h Height of the tile.
* @param {number} gutter Tile gutter.
*/
ol.renderer.canvas.TileLayer.prototype.drawTileImage = function(tile, frameState, layerState, x, y, w, h, gutter) {
var image = tile.getImage();
if (image) {
this.context.drawImage(image, gutter, gutter,
image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h);
}
};
/**
* @param {ol.Coordinate} coordinate Coordinate.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
@@ -187,188 +276,25 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
* @return {T|undefined} Callback result.
* @template S,T,U
*/
ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel = function(
pixel, frameState, callback, thisArg) {
var canvas = this.context.canvas;
var size = frameState.size;
var pixelRatio = frameState.pixelRatio;
canvas.width = size[0] * pixelRatio;
canvas.height = size[1] * pixelRatio;
this.composeFrame(frameState, this.getLayer().getLayerState(), this.context);
var imageData = this.context.getImageData(
pixel[0], pixel[1], 1, 1).data;
ol.renderer.canvas.TileLayer.prototype.forEachLayerAtCoordinate = function(
coordinate, frameState, callback, thisArg) {
var canvasPixel = ol.transform.apply(this.coordinateToCanvasPixelTransform_, coordinate);
var imageData = this.context.getImageData(canvasPixel[0], canvasPixel[1], 1, 1).data;
if (imageData[3] > 0) {
return callback.call(thisArg, this.getLayer(), imageData);
return callback.call(thisArg, this.getLayer(), imageData);
} else {
return undefined;
}
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @protected
* @inheritDoc
*/
ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, frameState, layerState) {
var tilesToDraw = this.renderedTiles;
if (tilesToDraw.length === 0) {
return;
}
var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState;
var center = viewState.center;
var projection = viewState.projection;
var resolution = viewState.resolution;
var rotation = viewState.rotation;
var size = frameState.size;
var offsetX = Math.round(pixelRatio * size[0] / 2);
var offsetY = Math.round(pixelRatio * size[1] / 2);
var pixelScale = pixelRatio / resolution;
var layer = this.getLayer();
var source = /** @type {ol.source.Tile} */ (layer.getSource());
var tileGutter = source.getTilePixelRatio(pixelRatio) * source.getGutter(projection);
var tileGrid = source.getTileGridForProjection(projection);
var hasRenderListeners = layer.hasListener(ol.render.Event.Type.RENDER);
var renderContext = context;
var drawScale = 1;
var drawOffsetX, drawOffsetY, drawSize;
if (rotation || hasRenderListeners) {
renderContext = this.context;
var renderCanvas = renderContext.canvas;
drawScale = source.getTilePixelRatio(pixelRatio) / pixelRatio;
var width = context.canvas.width * drawScale;
var height = context.canvas.height * drawScale;
// Make sure the canvas is big enough for all possible rotation angles
drawSize = Math.round(Math.sqrt(width * width + height * height));
if (renderCanvas.width != drawSize) {
renderCanvas.width = renderCanvas.height = drawSize;
} else {
renderContext.clearRect(0, 0, drawSize, drawSize);
}
drawOffsetX = (drawSize - width) / 2 / drawScale;
drawOffsetY = (drawSize - height) / 2 / drawScale;
pixelScale *= drawScale;
offsetX = Math.round(drawScale * (offsetX + drawOffsetX));
offsetY = Math.round(drawScale * (offsetY + drawOffsetY));
}
// for performance reasons, context.save / context.restore is not used
// to save and restore the transformation matrix and the opacity.
// see http://jsperf.com/context-save-restore-versus-variable
var alpha = renderContext.globalAlpha;
renderContext.globalAlpha = layerState.opacity;
var pixelExtents;
var opaque = source.getOpaque(projection) && layerState.opacity == 1;
if (!opaque) {
tilesToDraw.reverse();
pixelExtents = [];
}
var extent = layerState.extent;
var clipped = extent !== undefined;
if (clipped) {
var topLeft = ol.extent.getTopLeft(/** @type {ol.Extent} */ (extent));
var topRight = ol.extent.getTopRight(/** @type {ol.Extent} */ (extent));
var bottomRight = ol.extent.getBottomRight(/** @type {ol.Extent} */ (extent));
var bottomLeft = ol.extent.getBottomLeft(/** @type {ol.Extent} */ (extent));
ol.transform.apply(frameState.coordinateToPixelTransform, topLeft);
ol.transform.apply(frameState.coordinateToPixelTransform, topRight);
ol.transform.apply(frameState.coordinateToPixelTransform, bottomRight);
ol.transform.apply(frameState.coordinateToPixelTransform, bottomLeft);
var ox = drawOffsetX || 0;
var oy = drawOffsetY || 0;
renderContext.save();
var cx = (renderContext.canvas.width) / 2;
var cy = (renderContext.canvas.height) / 2;
ol.render.canvas.rotateAtOffset(renderContext, -rotation, cx, cy);
renderContext.beginPath();
renderContext.moveTo(drawScale * (topLeft[0] * pixelRatio + ox),
drawScale * (topLeft[1] * pixelRatio + oy));
renderContext.lineTo(drawScale * (topRight[0] * pixelRatio + ox),
drawScale * (topRight[1] * pixelRatio + oy));
renderContext.lineTo(drawScale * (bottomRight[0] * pixelRatio + ox),
drawScale * (bottomRight[1] * pixelRatio + oy));
renderContext.lineTo(drawScale * (bottomLeft[0] * pixelRatio + ox),
drawScale * (bottomLeft[1] * pixelRatio + oy));
renderContext.clip();
ol.render.canvas.rotateAtOffset(renderContext, rotation, cx, cy);
}
for (var i = 0, ii = tilesToDraw.length; i < ii; ++i) {
var tile = tilesToDraw[i];
var tileCoord = tile.getTileCoord();
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
var currentZ = tileCoord[0];
// Calculate all insert points by tile widths from a common origin to avoid
// gaps caused by rounding
var origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent(
tileGrid.getTileCoordForCoordAndZ(center, currentZ, this.tmpTileCoord_)));
var w = Math.round(ol.extent.getWidth(tileExtent) * pixelScale);
var h = Math.round(ol.extent.getHeight(tileExtent) * pixelScale);
var left = Math.round((tileExtent[0] - origin[0]) * pixelScale / w) * w +
offsetX + Math.round((origin[0] - center[0]) * pixelScale);
var top = Math.round((origin[1] - tileExtent[3]) * pixelScale / h) * h +
offsetY + Math.round((center[1] - origin[1]) * pixelScale);
if (!opaque) {
var pixelExtent = [left, top, left + w, top + h];
// Create a clip mask for regions in this low resolution tile that are
// already filled by a higher resolution tile
renderContext.save();
for (var j = 0, jj = pixelExtents.length; j < jj; ++j) {
var clipExtent = pixelExtents[j];
if (ol.extent.intersects(pixelExtent, clipExtent)) {
renderContext.beginPath();
// counter-clockwise (outer ring) for current tile
renderContext.moveTo(pixelExtent[0], pixelExtent[1]);
renderContext.lineTo(pixelExtent[0], pixelExtent[3]);
renderContext.lineTo(pixelExtent[2], pixelExtent[3]);
renderContext.lineTo(pixelExtent[2], pixelExtent[1]);
// clockwise (inner ring) for higher resolution tile
renderContext.moveTo(clipExtent[0], clipExtent[1]);
renderContext.lineTo(clipExtent[2], clipExtent[1]);
renderContext.lineTo(clipExtent[2], clipExtent[3]);
renderContext.lineTo(clipExtent[0], clipExtent[3]);
renderContext.closePath();
renderContext.clip();
}
}
pixelExtents.push(pixelExtent);
}
var tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
renderContext.drawImage(tile.getImage(), tileGutter, tileGutter,
tilePixelSize[0], tilePixelSize[1], left, top, w, h);
if (!opaque) {
renderContext.restore();
}
}
if (clipped) {
renderContext.restore();
}
if (hasRenderListeners) {
var dX = drawOffsetX - offsetX / drawScale + offsetX;
var dY = drawOffsetY - offsetY / drawScale + offsetY;
var imageTransform = ol.transform.compose(this.imageTransform_,
drawSize / 2 - dX, drawSize / 2 - dY,
pixelScale, -pixelScale,
-rotation,
-center[0] + dX / pixelScale, -center[1] - dY / pixelScale);
this.dispatchRenderEvent(renderContext, frameState, imageTransform);
}
if (rotation || hasRenderListeners) {
context.drawImage(renderContext.canvas, -Math.round(drawOffsetX),
-Math.round(drawOffsetY), drawSize / drawScale, drawSize / drawScale);
}
renderContext.globalAlpha = alpha;
ol.renderer.canvas.TileLayer.prototype.getImage = function() {
return this.context.canvas;
};
@@ -377,3 +303,11 @@ ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, fram
* @return {ol.layer.Tile|ol.layer.VectorTile}
*/
ol.renderer.canvas.TileLayer.prototype.getLayer;
/**
* @inheritDoc
*/
ol.renderer.canvas.TileLayer.prototype.getImageTransform = function() {
return this.imageTransform_;
};

View File

@@ -83,7 +83,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
var transform = this.getTransform(frameState, 0);
this.dispatchPreComposeEvent(context, frameState, transform);
this.preCompose(context, frameState, transform);
// clipped rendering if layer extent is set
var clipExtent = layerState.extent;
@@ -169,7 +169,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
if (clipped) {
context.restore();
}
this.dispatchPostComposeEvent(context, frameState, transform);
this.postCompose(context, frameState, layerState, transform);
};

View File

@@ -1,12 +1,10 @@
goog.provide('ol.renderer.canvas.VectorTileLayer');
goog.require('ol');
goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.proj');
goog.require('ol.proj.Units');
goog.require('ol.layer.VectorTile');
goog.require('ol.render.Event');
goog.require('ol.render.ReplayType');
goog.require('ol.render.canvas');
goog.require('ol.render.canvas.ReplayGroup');
@@ -66,126 +64,12 @@ ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS = {
};
/**
* @inheritDoc
*/
ol.renderer.canvas.VectorTileLayer.prototype.composeFrame = function(
frameState, layerState, context) {
var transform = this.getTransform(frameState, 0);
this.dispatchPreComposeEvent(context, frameState, transform);
// clipped rendering if layer extent is set
var extent = layerState.extent;
var clipped = extent !== undefined;
if (clipped) {
this.clip(context, frameState, /** @type {ol.Extent} */ (extent));
}
var renderMode = this.getLayer().getRenderMode();
if (renderMode !== ol.layer.VectorTile.RenderType.VECTOR) {
this.renderTileImages(context, frameState, layerState);
}
if (renderMode !== ol.layer.VectorTile.RenderType.IMAGE) {
this.renderTileReplays_(context, frameState, layerState);
}
if (clipped) {
context.restore();
}
this.dispatchPostComposeEvent(context, frameState, transform);
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @private
*/
ol.renderer.canvas.VectorTileLayer.prototype.renderTileReplays_ = function(
context, frameState, layerState) {
var layer = this.getLayer();
var replays = ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS[layer.getRenderMode()];
var pixelRatio = frameState.pixelRatio;
var skippedFeatureUids = layerState.managed ?
frameState.skippedFeatureUids : {};
var viewState = frameState.viewState;
var center = viewState.center;
var resolution = viewState.resolution;
var rotation = viewState.rotation;
var size = frameState.size;
var pixelScale = pixelRatio / resolution;
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var tilePixelRatio = source.getTilePixelRatio();
var transform = this.getTransform(frameState, 0);
var replayContext;
if (layer.hasListener(ol.render.Event.Type.RENDER)) {
// resize and clear
this.context.canvas.width = context.canvas.width;
this.context.canvas.height = context.canvas.height;
replayContext = this.context;
} else {
replayContext = context;
}
// for performance reasons, context.save / context.restore is not used
// to save and restore the transformation matrix and the opacity.
// see http://jsperf.com/context-save-restore-versus-variable
var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity;
/** @type {Array.<ol.VectorTile>} */
var tilesToDraw = this.renderedTiles;
var tileGrid = source.getTileGrid();
var currentZ, i, ii, offsetX, offsetY, origin, pixelSpace, replayState;
var tile, tileExtent, tilePixelResolution, tileResolution, tileTransform;
for (i = 0, ii = tilesToDraw.length; i < ii; ++i) {
tile = tilesToDraw[i];
replayState = tile.getReplayState();
tileExtent = tileGrid.getTileCoordExtent(
tile.getTileCoord(), this.tmpExtent);
currentZ = tile.getTileCoord()[0];
pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
tileResolution = tileGrid.getResolution(currentZ);
tilePixelResolution = tileResolution / tilePixelRatio;
offsetX = Math.round(pixelRatio * size[0] / 2);
offsetY = Math.round(pixelRatio * size[1] / 2);
if (pixelSpace) {
origin = ol.extent.getTopLeft(tileExtent);
tileTransform = ol.transform.reset(this.tmpTransform_);
tileTransform = ol.transform.compose(this.tmpTransform_,
offsetX, offsetY,
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
rotation,
(origin[0] - center[0]) / tilePixelResolution, (center[1] - origin[1]) / tilePixelResolution);
} else {
tileTransform = transform;
}
ol.render.canvas.rotateAtOffset(replayContext, -rotation, offsetX, offsetY);
replayState.replayGroup.replay(replayContext, pixelRatio,
tileTransform, rotation, skippedFeatureUids, replays);
ol.render.canvas.rotateAtOffset(replayContext, rotation, offsetX, offsetY);
}
if (replayContext != context) {
this.dispatchRenderEvent(replayContext, frameState, transform);
context.drawImage(replayContext.canvas, 0, 0);
}
replayContext.globalAlpha = alpha;
};
/**
* @param {ol.VectorTile} tile Tile.
* @param {olx.FrameState} frameState Frame state.
* @private
*/
ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(tile,
frameState) {
var layer = this.getLayer();
var pixelRatio = frameState.pixelRatio;
@@ -204,12 +88,11 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var tileGrid = source.getTileGrid();
var tileCoord = tile.getTileCoord();
var tileCoord = tile.tileCoord;
var tileProjection = tile.getProjection();
var pixelSpace = tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS;
var resolution = tileGrid.getResolution(tileCoord[0]);
var extent, reproject, tileResolution;
if (pixelSpace) {
if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) {
var tilePixelRatio = tileResolution = source.getTilePixelRatio();
var tileSize = ol.size.toSize(tileGrid.getTileSize(tileCoord[0]));
extent = [0, 0, tileSize[0] * tilePixelRatio, tileSize[1] * tilePixelRatio];
@@ -275,6 +158,21 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
};
/**
* @inheritDoc
*/
ol.renderer.canvas.VectorTileLayer.prototype.drawTileImage = function(
tile, frameState, layerState, x, y, w, h, gutter) {
var vectorTile = /** @type {ol.VectorTile} */ (tile);
this.createReplayGroup_(vectorTile, frameState);
var layer = this.getLayer();
if (layer.getRenderMode() != ol.layer.VectorTile.RenderType.VECTOR) {
this.renderTileImage_(vectorTile, frameState, layerState);
}
ol.renderer.canvas.TileLayer.prototype.drawTileImage.apply(this, arguments);
};
/**
* @inheritDoc
*/
@@ -295,9 +193,8 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
var tile, tileCoord, tileExtent, tilePixelRatio, tileResolution;
for (i = 0, ii = replayables.length; i < ii; ++i) {
tile = replayables[i];
tileCoord = tile.getTileCoord();
tileExtent = source.getTileGrid().getTileCoordExtent(tileCoord,
this.tmpExtent);
tileCoord = tile.tileCoord;
tileExtent = source.getTileGrid().getTileCoordExtent(tileCoord, this.tmpExtent);
if (!ol.extent.containsCoordinate(tileExtent, coordinate)) {
continue;
}
@@ -332,6 +229,41 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
};
/**
* @param {ol.Tile} tile Tile.
* @param {olx.FrameState} frameState Frame state.
* @return {ol.Transform} transform Transform.
* @private
*/
ol.renderer.canvas.VectorTileLayer.prototype.getReplayTransform_ = function(tile, frameState) {
if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
var layer = this.getLayer();
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var tileGrid = source.getTileGrid();
var tileCoord = tile.tileCoord;
var tileResolution =
tileGrid.getResolution(tileCoord[0]) / source.getTilePixelRatio();
var viewState = frameState.viewState;
var pixelRatio = frameState.pixelRatio;
var renderResolution = viewState.resolution / pixelRatio;
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
var center = viewState.center;
var origin = ol.extent.getTopLeft(tileExtent);
var size = frameState.size;
var offsetX = Math.round(pixelRatio * size[0] / 2);
var offsetY = Math.round(pixelRatio * size[1] / 2);
return ol.transform.compose(this.tmpTransform_,
offsetX, offsetY,
tileResolution / renderResolution, tileResolution / renderResolution,
viewState.rotation,
(origin[0] - center[0]) / tileResolution,
(center[1] - origin[1]) / tileResolution);
} else {
return this.getTransform(frameState, 0);
}
};
/**
* Handle changes in image style state.
* @param {ol.events.Event} event Image style change event.
@@ -345,17 +277,53 @@ ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ = function(
/**
* @inheritDoc
*/
ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame = function(frameState, layerState) {
var prepared = ol.renderer.canvas.TileLayer.prototype.prepareFrame.call(this, frameState, layerState);
if (prepared) {
var skippedFeatures = Object.keys(frameState.skippedFeatureUids_ || {});
for (var i = 0, ii = this.renderedTiles.length; i < ii; ++i) {
var tile = /** @type {ol.VectorTile} */ (this.renderedTiles[i]);
this.createReplayGroup(tile, frameState);
this.renderTileImage_(tile, frameState, layerState, skippedFeatures);
ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, frameState, layerState) {
var renderMode = this.getLayer().getRenderMode();
var replays = ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS[renderMode];
if (replays) {
var pixelRatio = frameState.pixelRatio;
var rotation = frameState.viewState.rotation;
var size = frameState.size;
var offsetX = Math.round(pixelRatio * size[0] / 2);
var offsetY = Math.round(pixelRatio * size[1] / 2);
var tiles = this.renderedTiles;
var clips = [];
var zs = [];
for (var i = tiles.length - 1; i >= 0; --i) {
var tile = /** @type {ol.VectorTile} */ (tiles[i]);
// Create a clip mask for regions in this low resolution tile that are
// already filled by a higher resolution tile
var transform = this.getReplayTransform_(tile, frameState);
var currentClip = tile.getReplayState().replayGroup.getClipCoords(transform);
var currentZ = tile.tileCoord[0];
context.save();
context.globalAlpha = layerState.opacity;
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
for (var j = 0, jj = clips.length; j < jj; ++j) {
var clip = clips[j];
if (currentZ < zs[j]) {
context.beginPath();
// counter-clockwise (outer ring) for current tile
context.moveTo(currentClip[0], currentClip[1]);
context.lineTo(currentClip[2], currentClip[3]);
context.lineTo(currentClip[4], currentClip[5]);
context.lineTo(currentClip[6], currentClip[7]);
// clockwise (inner ring) for higher resolution tile
context.moveTo(clip[6], clip[7]);
context.lineTo(clip[4], clip[5]);
context.lineTo(clip[2], clip[3]);
context.lineTo(clip[0], clip[1]);
context.clip();
}
}
var replayGroup = tile.getReplayState().replayGroup;
replayGroup.replay(context, pixelRatio, transform, rotation, {}, replays);
context.restore();
clips.push(currentClip);
zs.push(currentZ);
}
}
return prepared;
ol.renderer.canvas.TileLayer.prototype.postCompose.apply(this, arguments);
};
@@ -391,57 +359,38 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderFeature = function(feature, s
* @param {ol.VectorTile} tile Tile.
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @param {Array.<string>} skippedFeatures Skipped features.
* @private
*/
ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
tile, frameState, layerState, skippedFeatures) {
tile, frameState, layerState) {
var layer = this.getLayer();
var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()];
if (!replays) {
// do not create an image in 'vector' mode
return;
}
var pixelRatio = frameState.pixelRatio;
var replayState = tile.getReplayState();
var revision = layer.getRevision();
if (!ol.array.equals(replayState.skippedFeatures, skippedFeatures) ||
replayState.renderedTileRevision !== revision) {
replayState.skippedFeatures = skippedFeatures;
var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()];
if (replays && replayState.renderedTileRevision !== revision) {
replayState.renderedTileRevision = revision;
var tileContext = tile.getContext();
var tileCoord = tile.tileCoord;
var z = tile.tileCoord[0];
var pixelRatio = frameState.pixelRatio;
var source = layer.getSource();
var tileGrid = source.getTileGrid();
var currentZ = tile.getTileCoord()[0];
var resolution = tileGrid.getResolution(currentZ);
var tileSize = ol.size.toSize(tileGrid.getTileSize(currentZ));
var tileResolution = tileGrid.getResolution(currentZ);
var resolutionRatio = tileResolution / resolution;
var width = tileSize[0] * pixelRatio * resolutionRatio;
var height = tileSize[1] * pixelRatio * resolutionRatio;
tileContext.canvas.width = width / resolutionRatio + 0.5;
tileContext.canvas.height = height / resolutionRatio + 0.5;
tileContext.scale(1 / resolutionRatio, 1 / resolutionRatio);
tileContext.translate(width / 2, height / 2);
var pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
var pixelScale = pixelRatio / resolution;
var tilePixelRatio = source.getTilePixelRatio();
var tilePixelResolution = tileResolution / tilePixelRatio;
var tileExtent = tileGrid.getTileCoordExtent(
tile.getTileCoord(), this.tmpExtent);
var tileTransform = ol.transform.reset(this.tmpTransform_);
if (pixelSpace) {
ol.transform.scale(tileTransform,
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution);
ol.transform.translate(tileTransform,
-tileSize[0] * tilePixelRatio / 2, -tileSize[1] * tilePixelRatio / 2);
var transform = ol.transform.reset(this.tmpTransform_);
if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
var renderPixelRatio = pixelRatio / tilePixelRatio;
ol.transform.scale(transform, renderPixelRatio, renderPixelRatio);
} else {
var tileCenter = ol.extent.getCenter(tileExtent);
ol.transform.scale(tileTransform, pixelScale, -pixelScale);
ol.transform.translate(tileTransform, -tileCenter[0], -tileCenter[1]);
var resolution = tileGrid.getResolution(z);
var pixelScale = pixelRatio / resolution;
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
ol.transform.scale(transform, pixelScale, -pixelScale);
ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
}
replayState.replayGroup.replay(tileContext, pixelRatio,
tileTransform, 0, frameState.skippedFeatureUids || {}, replays);
var context = tile.getContext();
var size = source.getTilePixelSize(z, pixelRatio, frameState.viewState.projection);
context.canvas.width = size[0];
context.canvas.height = size[1];
replayState.replayGroup.replay(context, pixelRatio, transform, 0, {}, replays);
}
};

View File

@@ -9,7 +9,6 @@ goog.require('ol.events');
goog.require('ol.events.EventType');
goog.require('ol.functions');
goog.require('ol.source.State');
goog.require('ol.transform');
/**
@@ -45,29 +44,6 @@ ol.inherits(ol.renderer.Layer, ol.Observable);
ol.renderer.Layer.prototype.forEachFeatureAtCoordinate = ol.nullFunction;
/**
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState Frame state.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T
*/
ol.renderer.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
var coordinate = ol.transform.apply(
frameState.pixelToCoordinateTransform, pixel.slice());
var hasFeature = this.forEachFeatureAtCoordinate(
coordinate, frameState, ol.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.layer_, null);
} else {
return undefined;
}
};
/**
* @param {ol.Coordinate} coordinate Coordinate.
* @param {olx.FrameState} frameState Frame state.

View File

@@ -167,6 +167,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, fram
/**
* @abstract
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
@@ -181,29 +182,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, fram
* @template S,T,U
*/
ol.renderer.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
layerFilter, thisArg2) {
var result;
var viewState = frameState.viewState;
var viewResolution = viewState.resolution;
var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length;
var i;
for (i = numLayers - 1; i >= 0; --i) {
var layerState = layerStates[i];
var layer = layerState.layer;
if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
layerFilter.call(thisArg2, layer)) {
var layerRenderer = this.getLayerRenderer(layer);
result = layerRenderer.forEachLayerAtPixel(
pixel, frameState, callback, thisArg);
if (result) {
return result;
}
}
}
return undefined;
};
layerFilter, thisArg2) {};
/**

View File

@@ -219,13 +219,7 @@ ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordin
/**
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T,U
* @inheritDoc
*/
ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
if (!this.image_ || !this.image_.getImage()) {

View File

@@ -251,3 +251,16 @@ ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
* @return {boolean} whether composeFrame should be called.
*/
ol.renderer.webgl.Layer.prototype.prepareFrame = function(frameState, layerState, context) {};
/**
* @abstract
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T,U
*/
ol.renderer.webgl.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {};

View File

@@ -584,7 +584,7 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = function(pixel, frameState
var layer = layerState.layer;
if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) &&
layerFilter.call(thisArg, layer)) {
var layerRenderer = this.getLayerRenderer(layer);
var layerRenderer = /** @type {ol.renderer.webgl.Layer} */ (this.getLayerRenderer(layer));
result = layerRenderer.forEachLayerAtPixel(
pixel, frameState, callback, thisArg);
if (result) {

View File

@@ -358,13 +358,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerS
/**
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T,U
* @inheritDoc
*/
ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
if (!this.framebuffer) {

View File

@@ -154,13 +154,7 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = function(coordi
/**
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T,U
* @inheritDoc
*/
ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
var coordinate = ol.transform.apply(

View File

@@ -633,8 +633,7 @@ ol.TilePriorityFunction;
* renderedRenderOrder: (null|function(ol.Feature, ol.Feature):number),
* renderedTileRevision: number,
* renderedRevision: number,
* replayGroup: ol.render.ReplayGroup,
* skippedFeatures: Array.<string>}}
* replayGroup: ol.render.ReplayGroup}}
*/
ol.TileReplayState;

View File

@@ -59,8 +59,7 @@ ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
renderedRenderOrder: null,
renderedRevision: -1,
renderedTileRevision: -1,
replayGroup: null,
skippedFeatures: []
replayGroup: null
};
/**

View File

@@ -32,15 +32,18 @@ describe('ol.renderer.canvas.TileLayer', function() {
renderer.renderedTiles = [];
var frameState = {
viewState: {
center: [2, 3],
center: [10, 5],
projection: ol.proj.get('EPSG:3857'),
resolution: 1,
rotation: Math.PI
},
size: [10, 10],
extent: [0, 0, 20, 10],
size: [20, 10],
pixelRatio: 2,
coordinateToPixelTransform: ol.transform.create(),
pixelToCoordinateTransform: ol.transform.create()
pixelToCoordinateTransform: ol.transform.create(),
usedTiles: {},
wantedTiles: {}
};
renderer.getImageTransform = function() {
return ol.transform.create();
@@ -62,8 +65,9 @@ describe('ol.renderer.canvas.TileLayer', function() {
return img;
}
}];
renderer.prepareFrame(frameState, layerState);
renderer.composeFrame(frameState, layerState, context);
expect(context.drawImage.firstCall.args[0].width).to.be(112);
expect(context.drawImage.firstCall.args[0].width).to.be(17);
});
});

View File

@@ -89,7 +89,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
it('does not render images for pure vector rendering', function() {
layer.renderMode_ = 'vector';
var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'renderTileImages');
'renderTileImage_');
map.renderSync();
expect(spy.callCount).to.be(0);
spy.restore();
@@ -98,7 +98,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
it('does not render replays for pure image rendering', function() {
layer.renderMode_ = 'image';
var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'renderTileReplays_');
'getReplayTransform_');
map.renderSync();
expect(spy.callCount).to.be(0);
spy.restore();
@@ -106,9 +106,9 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
it('renders both replays and images for hybrid rendering', function() {
var spy1 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'renderTileReplays_');
'getReplayTransform_');
var spy2 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'renderTileImages');
'renderTileImage_');
map.renderSync();
expect(spy1.callCount).to.be(1);
expect(spy2.callCount).to.be(1);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB