Merge pull request #5724 from ahocevar/fix-tilelayer-extent

Fix clipping of the tile layer extent on HiDPI devices
This commit is contained in:
Andreas Hocevar
2016-08-23 12:12:40 +02:00
committed by GitHub
6 changed files with 88 additions and 18 deletions

View File

@@ -12,7 +12,6 @@ goog.require('ol.extent');
goog.require('ol.render.canvas');
goog.require('ol.render.EventType');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.size');
/**
@@ -240,14 +239,12 @@ ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, fram
var hasRenderListeners = layer.hasListener(ol.render.EventType.RENDER);
var renderContext = context;
var drawOffsetX, drawOffsetY, drawScale, drawSize;
var drawScale = 1;
var drawOffsetX, drawOffsetY, drawSize;
if (rotation || hasRenderListeners) {
renderContext = this.context;
var renderCanvas = renderContext.canvas;
var drawZ = tileGrid.getZForResolution(resolution);
var drawTileSize = source.getTilePixelSize(drawZ, pixelRatio, projection);
var tileSize = ol.size.toSize(tileGrid.getTileSize(drawZ));
drawScale = drawTileSize[0] / tileSize[0];
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
@@ -294,14 +291,18 @@ ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, fram
var ox = drawOffsetX || 0;
var oy = drawOffsetY || 0;
renderContext.save();
var cx = (renderContext.canvas.width * pixelRatio) / 2;
var cy = (renderContext.canvas.height * pixelRatio) / 2;
var cx = (renderContext.canvas.width) / 2;
var cy = (renderContext.canvas.height) / 2;
ol.render.canvas.rotateAtOffset(renderContext, -rotation, cx, cy);
renderContext.beginPath();
renderContext.moveTo(topLeft[0] * pixelRatio + ox, topLeft[1] * pixelRatio + oy);
renderContext.lineTo(topRight[0] * pixelRatio + ox, topRight[1] * pixelRatio + oy);
renderContext.lineTo(bottomRight[0] * pixelRatio + ox, bottomRight[1] * pixelRatio + oy);
renderContext.lineTo(bottomLeft[0] * pixelRatio + ox, bottomLeft[1] * pixelRatio + oy);
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);
}

View File

@@ -0,0 +1,48 @@
goog.provide('ol.test.renderer.canvas.TileLayer');
goog.require('ol.transform');
goog.require('ol.layer.Tile');
goog.require('ol.renderer.Map');
goog.require('ol.renderer.canvas.TileLayer');
goog.require('ol.source.XYZ');
describe('ol.renderer.canvas.TileLayer', function() {
describe('#composeFrame()', function() {
it('uses correct draw scale when rotating (HiDPI)', function() {
var layer = new ol.layer.Tile({
source: new ol.source.XYZ()
});
var renderer = new ol.renderer.canvas.TileLayer(layer);
renderer.renderedTiles = [];
var frameState = {
viewState: {
center: [2, 3],
projection: ol.proj.get('EPSG:3857'),
resolution: 1,
rotation: Math.PI
},
size: [10, 10],
pixelRatio: 2,
coordinateToPixelTransform: ol.transform.create(),
pixelToCoordinateTransform: ol.transform.create()
};
renderer.getImageTransform = function() {
return ol.transform.create();
};
ol.renderer.Map.prototype.calculateMatrices2D(frameState);
var layerState = layer.getLayerState();
var canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 100;
var context = {
canvas: canvas,
drawImage: sinon.spy()
};
renderer.composeFrame(frameState, layerState, context);
expect(context.drawImage.firstCall.args[0].width).to.be(112);
});
});
});

View File

@@ -265,11 +265,13 @@ describe('ol.source.TileWMS', function() {
});
describe('#setUrl()', function() {
var source = new ol.source.TileWMS(options);
var url = 'http://foo/';
source.setUrl(url);
var tileUrl = source.tileUrlFunction([0, 0, 0], 1, ol.proj.get('EPSG:4326'));
expect(tileUrl.indexOf(url)).to.be(0);
it('sets the correct url', function() {
var source = new ol.source.TileWMS(options);
var url = 'http://foo/';
source.setUrl(url);
var tileUrl = source.tileUrlFunction([0, 0, 0], 1, ol.proj.get('EPSG:4326'));
expect(tileUrl.indexOf(url)).to.be(0);
});
});
describe('#setUrls()', function() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -19,11 +19,12 @@ describe('ol.rendering.layer.Tile', function() {
var target, map;
function createMap(renderer, opt_center, opt_size) {
function createMap(renderer, opt_center, opt_size, opt_pixelRatio) {
var size = opt_size !== undefined ? opt_size : [50, 50];
target = createMapDiv(size[0], size[1]);
map = new ol.Map({
pixelRatio: opt_pixelRatio || 1,
target: target,
renderer: renderer,
view: new ol.View({
@@ -152,6 +153,24 @@ describe('ol.rendering.layer.Tile', function() {
IMAGE_TOLERANCE, done);
});
});
it('tests canvas layer extent clipping (HiDPI)', function(done) {
map = createMap('canvas', undefined, undefined, 2);
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
expectResemble(map, 'spec/ol/layer/expected/2-layers-canvas-extent-hidpi.png',
IMAGE_TOLERANCE, done);
});
});
it('tests canvas layer extent clipping with rotation (HiDPI)', function(done) {
map = createMap('canvas', undefined, undefined, 2);
map.getView().setRotation(Math.PI / 2);
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
expectResemble(map, 'spec/ol/layer/expected/2-layers-canvas-extent-rotate-hidpi.png',
IMAGE_TOLERANCE, done);
});
});
});
describe('tile layer with opacity', function() {