Avoid clipping by rendering tiles with rotated labels

This only works when the device pixel ratio is 1. Labels are incorrectly
positioned and not at all rotated for other pixel ratios. I cannot find the
cause for this problem.
This commit is contained in:
Andreas Hocevar
2015-12-15 23:24:09 +01:00
parent c1b16217f2
commit 4f2df30f1d

View File

@@ -52,18 +52,6 @@ ol.renderer.canvas.VectorTileLayer = function(layer) {
*/ */
this.renderedTiles_ = []; this.renderedTiles_ = [];
/**
* @private
* @type {number}
*/
this.resolution_ = NaN;
/**
* @private
* @type {number}
*/
this.rotation_ = NaN;
/** /**
* @private * @private
* @type {ol.Extent} * @type {ol.Extent}
@@ -123,15 +111,12 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
// see http://jsperf.com/context-save-restore-versus-variable // see http://jsperf.com/context-save-restore-versus-variable
var alpha = replayContext.globalAlpha; var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity; replayContext.globalAlpha = layerState.opacity;
var imageSmoothingEnabled = replayContext.imageSmoothingEnabled;
replayContext.imageSmoothingEnabled = false;
var tilesToDraw = this.renderedTiles_; var tilesToDraw = this.renderedTiles_;
var tileGrid = source.getTileGrid(); var tileGrid = source.getTileGrid();
var currentZ, height, i, ii, insertPoint, insertTransform, origin, pixelScale; var currentZ, height, i, ii, insertPoint, insertTransform, offsetX, offsetY;
var pixelSpace, replayState, rotatedTileExtent, rotatedTileSize, size, tile; var origin, pixelScale, pixelSpace, replayState, scale, size, tile;
var tileCenter, tileContext, tileExtent, tilePixelResolution, tilePixelSize; var tileCenter, tileContext, tileExtent, tilePixelResolution, tilePixelSize;
var tileResolution, tileSize, tileTransform, width; var tileResolution, tileSize, tileTransform, width;
for (i = 0, ii = tilesToDraw.length; i < ii; ++i) { for (i = 0, ii = tilesToDraw.length; i < ii; ++i) {
@@ -155,7 +140,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
if (pixelSpace) { if (pixelSpace) {
origin = ol.extent.getTopLeft(tileExtent); origin = ol.extent.getTopLeft(tileExtent);
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_, tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
pixelRatio * size[0] / 2, pixelRatio * size[1] / 2, offsetX, offsetY,
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
rotation, rotation,
@@ -167,21 +152,17 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
replayState.replayGroup.replay(replayContext, pixelRatio, replayState.replayGroup.replay(replayContext, pixelRatio,
tileTransform, rotation, skippedFeatureUids); tileTransform, rotation, skippedFeatureUids);
} else { } else {
rotatedTileExtent = ol.extent.getForViewAndSize(
ol.extent.getCenter(tileExtent), tileResolution, rotation, tileSize);
rotatedTileSize = [ol.extent.getWidth(rotatedTileExtent),
ol.extent.getHeight(rotatedTileExtent)];
tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection); tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
if (pixelSpace) { if (pixelSpace) {
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_, tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
width / 2, height / 2, 0, 0,
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution, pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
rotation, rotation,
-tilePixelSize[0] / 2, -tilePixelSize[1] / 2); -tilePixelSize[0] / 2, -tilePixelSize[1] / 2);
} else { } else {
tileCenter = ol.extent.getCenter(rotatedTileExtent); tileCenter = ol.extent.getCenter(tileExtent);
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_, tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
width / 2, height / 2, 0, 0,
pixelScale, -pixelScale, pixelScale, -pixelScale,
-rotation, -rotation,
-tileCenter[0], -tileCenter[1]); -tileCenter[0], -tileCenter[1]);
@@ -193,31 +174,29 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
replayState.rotation = rotation; replayState.rotation = rotation;
tileContext.canvas.width = width + 0.5; tileContext.canvas.width = width + 0.5;
tileContext.canvas.height = height + 0.5; tileContext.canvas.height = height + 0.5;
tileContext.translate(width / 2, height / 2);
tileContext.rotate(-rotation);
replayState.replayGroup.replay(tileContext, pixelRatio, replayState.replayGroup.replay(tileContext, pixelRatio,
tileTransform, rotation, skippedFeatureUids, rotation !== 0); tileTransform, rotation, skippedFeatureUids, false);
} }
insertTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_, insertTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
(pixelRatio * size[0] - width) / 2, 0, 0, pixelScale, -pixelScale, 0, -center[0], -center[1]);
(pixelRatio * size[1] - height) / 2,
pixelScale, -pixelScale,
-rotation,
-center[0], -center[1]);
insertPoint = ol.geom.flat.transform.transform2D( insertPoint = ol.geom.flat.transform.transform2D(
ol.extent.getCenter(rotatedTileExtent), 0, 1, 2, insertTransform); ol.extent.getTopLeft(tileExtent), 0, 1, 2, insertTransform);
replayContext.translate(offsetX, offsetY);
replayContext.rotate(rotation);
replayContext.drawImage(tileContext.canvas, replayContext.drawImage(tileContext.canvas,
insertPoint[0], insertPoint[1]); Math.round(insertPoint[0]), Math.round(insertPoint[1]));
replayContext.rotate(-rotation);
replayContext.translate(-offsetX, -offsetY);
} }
} }
this.resolution_ = resolution;
this.rotation_ = rotation;
if (replayContext != context) { if (replayContext != context) {
this.dispatchRenderEvent(replayContext, frameState, transform); this.dispatchRenderEvent(replayContext, frameState, transform);
context.drawImage(replayContext.canvas, 0, 0); context.drawImage(replayContext.canvas, 0, 0);
} }
replayContext.globalAlpha = alpha; replayContext.globalAlpha = alpha;
replayContext.imageSmoothingEnabled = imageSmoothingEnabled;
this.dispatchPostComposeEvent(context, frameState, transform); this.dispatchPostComposeEvent(context, frameState, transform);
}; };