Merge pull request #4960 from ahocevar/clip-rendered

Simplify clipping of lower resolution regions
This commit is contained in:
Andreas Hocevar
2016-03-03 15:44:47 +01:00
parent afb8efc0e9
commit d12dce1c03

View File

@@ -9,7 +9,6 @@ goog.require('ol.array');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.object');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.renderer.canvas.Layer'); goog.require('ol.renderer.canvas.Layer');
goog.require('ol.source.Tile'); goog.require('ol.source.Tile');
@@ -24,12 +23,6 @@ ol.renderer.canvas.TileLayer = function(tileLayer) {
goog.base(this, tileLayer); goog.base(this, tileLayer);
/**
* @private
* @type {!Object.<string, Array.<ol.TileCoord>>}
*/
this.clipTileCoords_ = {};
/** /**
* @private * @private
* @type {CanvasRenderingContext2D} * @type {CanvasRenderingContext2D}
@@ -95,60 +88,56 @@ ol.renderer.canvas.TileLayer.prototype.composeFrame = function(
var tileGrid = source.getTileGridForProjection(projection); var tileGrid = source.getTileGridForProjection(projection);
var tilesToDraw = this.renderedTiles_; var tilesToDraw = this.renderedTiles_;
var clipExtent, clipH, clipLeft, clipOrigin, clipTileCoord, clipTileCoords; var pixelExtents;
var clipTop, clipW, currentZ, h, i, ii, j, jj, left, origin, tile, tileExtent; var opaque = source.getOpaque(projection) && layerState.opacity == 1;
var tilePixelSize, top, w; if (!opaque) {
for (i = 0, ii = tilesToDraw.length; i < ii; ++i) { tilesToDraw.reverse();
tile = tilesToDraw[i]; pixelExtents = [];
tileExtent = tileGrid.getTileCoordExtent( }
tile.getTileCoord(), this.tmpExtent_); for (var i = 0, ii = tilesToDraw.length; i < ii; ++i) {
currentZ = tile.getTileCoord()[0]; 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 // Calculate all insert points by tile widths from a common origin to avoid
// gaps caused by rounding // gaps caused by rounding
origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent( var origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent(
tileGrid.getTileCoordForCoordAndZ(center, currentZ))); tileGrid.getTileCoordForCoordAndZ(center, currentZ)));
w = Math.round(ol.extent.getWidth(tileExtent) * pixelScale); var w = Math.round(ol.extent.getWidth(tileExtent) * pixelScale);
h = Math.round(ol.extent.getHeight(tileExtent) * pixelScale); var h = Math.round(ol.extent.getHeight(tileExtent) * pixelScale);
left = Math.round((tileExtent[0] - origin[0]) * pixelScale / w) * w + var left = Math.round((tileExtent[0] - origin[0]) * pixelScale / w) * w +
offsetX + Math.round((origin[0] - center[0]) * pixelScale); offsetX + Math.round((origin[0] - center[0]) * pixelScale);
top = Math.round((origin[1] - tileExtent[3]) * pixelScale / h) * h + var top = Math.round((origin[1] - tileExtent[3]) * pixelScale / h) * h +
offsetY + Math.round((center[1] - origin[1]) * pixelScale); offsetY + Math.round((center[1] - origin[1]) * pixelScale);
clipTileCoords = this.clipTileCoords_[tile.tileCoord.toString()]; if (!opaque) {
if (clipTileCoords) { var pixelExtent = [left, top, left + w, top + h];
// Create a clip mask for regions in this low resolution tile that will be // Create a clip mask for regions in this low resolution tile that are
// filled by a higher resolution tile // already filled by a higher resolution tile
renderContext.save(); renderContext.save();
renderContext.beginPath(); for (var j = 0, jj = pixelExtents.length; j < jj; ++j) {
// counter-clockwise (outer ring) for current tile var clipExtent = pixelExtents[j];
renderContext.moveTo(left + w, top); if (ol.extent.intersects(pixelExtent, clipExtent)) {
renderContext.lineTo(left, top); renderContext.beginPath();
renderContext.lineTo(left, top + h); // counter-clockwise (outer ring) for current tile
renderContext.lineTo(left + w, top + h); renderContext.moveTo(pixelExtent[0], pixelExtent[1]);
renderContext.closePath(); renderContext.lineTo(pixelExtent[0], pixelExtent[3]);
// clockwise (inner rings) for lower resolution tiles renderContext.lineTo(pixelExtent[2], pixelExtent[3]);
for (j = 0, jj = clipTileCoords.length; j < jj; ++j) { renderContext.lineTo(pixelExtent[2], pixelExtent[1]);
clipTileCoord = clipTileCoords[j]; // clockwise (inner ring) for higher resolution tile
clipExtent = tileGrid.getTileCoordExtent(clipTileCoord); renderContext.moveTo(clipExtent[0], clipExtent[1]);
clipOrigin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent( renderContext.lineTo(clipExtent[2], clipExtent[1]);
tileGrid.getTileCoordForCoordAndZ(center, clipTileCoord[0]))); renderContext.lineTo(clipExtent[2], clipExtent[3]);
clipW = Math.round(ol.extent.getWidth(clipExtent) * pixelScale); renderContext.lineTo(clipExtent[0], clipExtent[3]);
clipH = Math.round(ol.extent.getHeight(clipExtent) * pixelScale); renderContext.closePath();
clipLeft = Math.round((clipExtent[0] - clipOrigin[0]) * pixelScale / clipW) * clipW + renderContext.clip();
offsetX + Math.round((clipOrigin[0] - center[0]) * pixelScale); }
clipTop = Math.round((clipOrigin[1] - clipExtent[3]) * pixelScale / clipH) * clipH +
offsetY + Math.round((center[1] - clipOrigin[1]) * pixelScale);
renderContext.moveTo(clipLeft, clipTop + clipH);
renderContext.lineTo(clipLeft, clipTop);
renderContext.lineTo(clipLeft + clipW, clipTop);
renderContext.lineTo(clipLeft + clipW, clipTop + clipH);
renderContext.closePath();
} }
renderContext.clip(); pixelExtents.push(pixelExtent);
} }
tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection); var tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
renderContext.drawImage(tile.getImage(), tileGutter, tileGutter, renderContext.drawImage(tile.getImage(), tileGutter, tileGutter,
tilePixelSize[0], tilePixelSize[1], left, top, w, h); tilePixelSize[0], tilePixelSize[1], left, top, w, h);
if (clipTileCoords) { if (!opaque) {
renderContext.restore(); renderContext.restore();
} }
} }
@@ -266,33 +255,6 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(
} }
} }
this.renderedTiles_ = renderables; this.renderedTiles_ = renderables;
ol.object.clear(this.clipTileCoords_);
if (!(tileSource.getOpaque(projection) && layerState.opacity == 1)) {
var clipTileCoords = this.clipTileCoords_;
var tileCoord;
for (i = renderables.length - 1; i >= 0; --i) {
tileCoord = renderables[i].getTileCoord();
tileGrid.forEachTileCoordParentTileRange(tileCoord,
function(z, tileRange) {
var tiles = tilesToDrawByZ[z];
if (tiles) {
var key, tile;
for (key in tiles) {
tile = tiles[key];
if (tileRange.contains(tile.getTileCoord()) &&
tile.getState() == ol.TileState.LOADED) {
if (!(key in clipTileCoords)) {
clipTileCoords[key] = [];
}
clipTileCoords[key].push(tileCoord);
return true;
}
}
}
return false;
}, this, tmpTileRange, tmpExtent);
}
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio, this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,