diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index dcbadb162c..ccf1db3d2e 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -287,11 +287,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = /** @type {Array.} */ var tilesToClear = []; - var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { - return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; - }, tileSource, pixelRatio, projection); - var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, getTileIfLoaded); + var findLoadedTiles = this.createLoadedTileFinder(tileSource, tilesToDrawByZ); var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError(); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index cfcb766990..091de7701d 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -128,11 +128,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { - return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; - }, tileSource, pixelRatio, projection); - var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, getTileIfLoaded); + var findLoadedTiles = this.createLoadedTileFinder(tileSource, tilesToDrawByZ); var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError(); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 0682ccb159..aab54f9306 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -85,6 +85,33 @@ ol.renderer.Layer.prototype.forEachLayerAtPixel = ol.renderer.Layer.prototype.hasFeatureAtCoordinate = goog.functions.FALSE; +/** + * Create a function that adds loaded tiles to the tile lookup. + * @param {ol.source.Tile} source Tile source. + * @param {Object.>} tiles Lookup of loaded + * tiles by zoom level. + * @return {function(number, ol.TileRange):boolean} A function that can be + * called with a zoom level and a tile range to add loaded tiles to the + * lookup. + * @protected + */ +ol.renderer.Layer.prototype.createLoadedTileFinder = function(source, tiles) { + /** + * @param {number} zoom Zoom level. + * @param {ol.TileRange} tileRange Tile range. + * @return {boolean} The tile range is fully loaded. + */ + return function(zoom, tileRange) { + return source.forEachLoadedTile(zoom, tileRange, function(tile) { + if (!tiles[zoom]) { + tiles[zoom] = {}; + } + tiles[zoom][tile.tileCoord.toString()] = tile; + }); + }; +}; + + /** * @protected * @return {ol.layer.Layer} Layer. diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index a73ea4f1fd..b652126324 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -94,6 +94,40 @@ ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() { }; +/** + * Create a function that adds loaded tiles to the tile lookup. + * @param {ol.source.Tile} source Tile source. + * @param {Object.>} tiles Lookup of loaded + * tiles by zoom level. + * @return {function(number, ol.TileRange):boolean} A function that can be + * called with a zoom level and a tile range to add loaded tiles to the + * lookup. + * @protected + */ +ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder = + function(source, tiles) { + var mapRenderer = this.mapRenderer; + + /** + * @param {number} zoom Zoom level. + * @param {ol.TileRange} tileRange Tile range. + * @return {boolean} The tile range is fully loaded. + */ + return function(zoom, tileRange) { + return source.forEachLoadedTile(zoom, tileRange, function(tile) { + var loaded = mapRenderer.isTileTextureLoaded(tile); + if (loaded) { + if (!tiles[zoom]) { + tiles[zoom] = {}; + } + tiles[zoom][tile.tileCoord.toString()] = tile; + } + return loaded; + }); + }; +}; + + /** * @inheritDoc */ @@ -190,12 +224,8 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) { - return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED && - mapRenderer.isTileTextureLoaded(tile); - }, tileSource, pixelRatio, projection); - var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ, getTileIfLoaded); + var findLoadedTiles = this.createLoadedTileFinder( + tileSource, tilesToDrawByZ); var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError(); var allTilesLoaded = true; diff --git a/src/ol/source/tiledebugsource.js b/src/ol/source/tiledebugsource.js index 79d05fc58e..ae49401d95 100644 --- a/src/ol/source/tiledebugsource.js +++ b/src/ol/source/tiledebugsource.js @@ -1,7 +1,6 @@ goog.provide('ol.source.TileDebug'); goog.require('ol.Tile'); -goog.require('ol.TileCache'); goog.require('ol.TileCoord'); goog.require('ol.TileState'); goog.require('ol.dom'); @@ -89,42 +88,20 @@ ol.source.TileDebug = function(options) { tileGrid: options.tileGrid }); - /** - * @private - * @type {ol.TileCache} - */ - this.tileCache_ = new ol.TileCache(); - }; goog.inherits(ol.source.TileDebug, ol.source.Tile); -/** - * @inheritDoc - */ -ol.source.TileDebug.prototype.canExpireCache = function() { - return this.tileCache_.canExpireCache(); -}; - - -/** - * @inheritDoc - */ -ol.source.TileDebug.prototype.expireCache = function(usedTiles) { - this.tileCache_.expireCache(usedTiles); -}; - - /** * @inheritDoc */ ol.source.TileDebug.prototype.getTile = function(z, x, y) { var tileCoordKey = this.getKeyZXY(z, x, y); - if (this.tileCache_.containsKey(tileCoordKey)) { - return /** @type {!ol.DebugTile_} */ (this.tileCache_.get(tileCoordKey)); + if (this.tileCache.containsKey(tileCoordKey)) { + return /** @type {!ol.DebugTile_} */ (this.tileCache.get(tileCoordKey)); } else { var tile = new ol.DebugTile_([z, x, y], this.tileGrid); - this.tileCache_.set(tileCoordKey, tile); + this.tileCache.set(tileCoordKey, tile); return tile; } }; diff --git a/src/ol/source/tileimagesource.js b/src/ol/source/tileimagesource.js index 1e53f22d10..9b1babe5d2 100644 --- a/src/ol/source/tileimagesource.js +++ b/src/ol/source/tileimagesource.js @@ -4,7 +4,6 @@ goog.require('goog.asserts'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('ol.ImageTile'); -goog.require('ol.TileCache'); goog.require('ol.TileCoord'); goog.require('ol.TileLoadFunctionType'); goog.require('ol.TileState'); @@ -53,12 +52,6 @@ ol.source.TileImage = function(options) { this.crossOrigin = goog.isDef(options.crossOrigin) ? options.crossOrigin : null; - /** - * @protected - * @type {ol.TileCache} - */ - this.tileCache = new ol.TileCache(); - /** * @protected * @type {ol.TileLoadFunctionType} @@ -87,22 +80,6 @@ ol.source.TileImage.defaultTileLoadFunction = function(imageTile, src) { }; -/** - * @inheritDoc - */ -ol.source.TileImage.prototype.canExpireCache = function() { - return this.tileCache.canExpireCache(); -}; - - -/** - * @inheritDoc - */ -ol.source.TileImage.prototype.expireCache = function(usedTiles) { - this.tileCache.expireCache(usedTiles); -}; - - /** * @inheritDoc */ diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index 504910ae84..3a326bd264 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -5,7 +5,9 @@ goog.require('goog.events.Event'); goog.require('goog.functions'); goog.require('ol.Attribution'); goog.require('ol.Extent'); +goog.require('ol.TileCache'); goog.require('ol.TileRange'); +goog.require('ol.TileState'); goog.require('ol.source.Source'); goog.require('ol.tilecoord'); goog.require('ol.tilegrid.TileGrid'); @@ -65,6 +67,12 @@ ol.source.Tile = function(options) { */ this.tileGrid = goog.isDef(options.tileGrid) ? options.tileGrid : null; + /** + * @protected + * @type {ol.TileCache} + */ + this.tileCache = new ol.TileCache(); + }; goog.inherits(ol.source.Tile, ol.source.Source); @@ -72,51 +80,47 @@ goog.inherits(ol.source.Tile, ol.source.Source); /** * @return {boolean} Can expire cache. */ -ol.source.Tile.prototype.canExpireCache = goog.functions.FALSE; +ol.source.Tile.prototype.canExpireCache = function() { + return this.tileCache.canExpireCache(); +}; /** * @param {Object.} usedTiles Used tiles. */ -ol.source.Tile.prototype.expireCache = goog.abstractMethod; +ol.source.Tile.prototype.expireCache = function(usedTiles) { + this.tileCache.expireCache(usedTiles); +}; /** - * Look for loaded tiles over a given tile range and zoom level. Adds - * properties to the provided lookup representing key/tile pairs for already - * loaded tiles. - * - * @param {Object.>} loadedTilesByZ A lookup of - * loaded tiles by zoom level. - * @param {function(number, number, number): ol.Tile} getTileIfLoaded A function - * that returns the tile only if it is fully loaded. * @param {number} z Zoom level. * @param {ol.TileRange} tileRange Tile range. + * @param {function(ol.Tile):(boolean|undefined)} callback Called with each + * loaded tile. If the callback returns `false`, the tile will not be + * considered loaded. * @return {boolean} The tile range is fully covered with loaded tiles. */ -ol.source.Tile.prototype.findLoadedTiles = function(loadedTilesByZ, - getTileIfLoaded, z, tileRange) { - // FIXME this could be more efficient about filling partial holes - var fullyCovered = true; - var tile, tileCoordKey, x, y; - for (x = tileRange.minX; x <= tileRange.maxX; ++x) { - for (y = tileRange.minY; y <= tileRange.maxY; ++y) { +ol.source.Tile.prototype.forEachLoadedTile = function(z, tileRange, callback) { + var covered = true; + var tile, tileCoordKey, loaded; + for (var x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (var y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoordKey = this.getKeyZXY(z, x, y); - if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) { - continue; - } - tile = getTileIfLoaded(z, x, y); - if (!goog.isNull(tile)) { - if (!loadedTilesByZ[z]) { - loadedTilesByZ[z] = {}; + loaded = false; + if (this.tileCache.containsKey(tileCoordKey)) { + tile = /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey)); + loaded = tile.getState() === ol.TileState.LOADED; + if (loaded) { + loaded = (callback(tile) !== false); } - loadedTilesByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; + } + if (!loaded) { + covered = false; } } } - return fullyCovered; + return covered; }; diff --git a/src/ol/source/tileutfgridsource.js b/src/ol/source/tileutfgridsource.js index 4a58b2bdfa..7a476840f5 100644 --- a/src/ol/source/tileutfgridsource.js +++ b/src/ol/source/tileutfgridsource.js @@ -7,7 +7,6 @@ goog.require('goog.events.EventType'); goog.require('goog.net.Jsonp'); goog.require('ol.Attribution'); goog.require('ol.Tile'); -goog.require('ol.TileCache'); goog.require('ol.TileState'); goog.require('ol.TileUrlFunction'); goog.require('ol.extent'); @@ -46,12 +45,6 @@ ol.source.TileUTFGrid = function(options) { */ this.tileUrlFunction_ = ol.TileUrlFunction.nullTileUrlFunction; - /** - * @private - * @type {!ol.TileCache} - */ - this.tileCache_ = new ol.TileCache(); - /** * @private * @type {string|undefined} @@ -64,22 +57,6 @@ ol.source.TileUTFGrid = function(options) { goog.inherits(ol.source.TileUTFGrid, ol.source.Tile); -/** - * @inheritDoc - */ -ol.source.TileUTFGrid.prototype.canExpireCache = function() { - return this.tileCache_.canExpireCache(); -}; - - -/** - * @inheritDoc - */ -ol.source.TileUTFGrid.prototype.expireCache = function(usedTiles) { - this.tileCache_.expireCache(usedTiles); -}; - - /** * @return {string|undefined} The template from TileJSON. * @api @@ -195,8 +172,8 @@ ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) { ol.source.TileUTFGrid.prototype.getTile = function(z, x, y, pixelRatio, projection) { var tileCoordKey = this.getKeyZXY(z, x, y); - if (this.tileCache_.containsKey(tileCoordKey)) { - return /** @type {!ol.Tile} */ (this.tileCache_.get(tileCoordKey)); + if (this.tileCache.containsKey(tileCoordKey)) { + return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey)); } else { goog.asserts.assert(projection); var tileCoord = [z, x, y]; @@ -207,7 +184,7 @@ ol.source.TileUTFGrid.prototype.getTile = goog.isDef(tileUrl) ? tileUrl : '', this.tileGrid.getTileCoordExtent(tileCoord), this.preemptive_); - this.tileCache_.set(tileCoordKey, tile); + this.tileCache.set(tileCoordKey, tile); return tile; } }; @@ -218,8 +195,8 @@ ol.source.TileUTFGrid.prototype.getTile = */ ol.source.TileUTFGrid.prototype.useTile = function(z, x, y) { var tileCoordKey = this.getKeyZXY(z, x, y); - if (this.tileCache_.containsKey(tileCoordKey)) { - this.tileCache_.get(tileCoordKey); + if (this.tileCache.containsKey(tileCoordKey)) { + this.tileCache.get(tileCoordKey); } }; diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index d2340c0a44..3024a1cfcb 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -12,176 +12,105 @@ describe('ol.source.Tile', function() { }); }); - describe('#findLoadedTiles()', function() { + describe('#forEachLoadedTile()', function() { - it('adds no tiles if none are already loaded', function() { - // a source with no loaded tiles + var callback; + beforeEach(function() { + callback = sinon.spy(); + }); + + it('does not call the callback if no tiles are loaded', function() { var source = new ol.test.source.TileMock({}); - - var loadedTilesByZ = {}; var grid = source.getTileGrid(); var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 3); + var zoom = 3; + var range = grid.getTileRangeForExtentAndZ(extent, zoom); - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 3, range); - - var keys = goog.object.getKeys(loadedTilesByZ); - expect(keys.length).to.be(0); + source.forEachLoadedTile(zoom, range, callback); + expect(callback.callCount).to.be(0); }); - it('adds loaded tiles to the lookup (z: 0)', function() { - // a source with no loaded tiles - var source = new ol.test.source.TileMock({ - '0/0/0': true, - '1/0/0': true - }); - - var loadedTilesByZ = {}; - var grid = source.getTileGrid(); - var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 0); - - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 0, range); - var keys = goog.object.getKeys(loadedTilesByZ); - expect(keys.length).to.be(1); - var tile = loadedTilesByZ['0']['0/0/0']; - expect(tile).to.be.a(ol.Tile); - expect(tile.state).to.be(ol.TileState.LOADED); - }); - - it('adds loaded tiles to the lookup (z: 1)', function() { - // a source with no loaded tiles - var source = new ol.test.source.TileMock({ - '0/0/0': true, - '1/0/0': true - }); - - var loadedTilesByZ = {}; - var grid = source.getTileGrid(); - var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 1); - - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - source.findLoadedTiles(loadedTilesByZ, getTileIfLoaded, 1, range); - var keys = goog.object.getKeys(loadedTilesByZ); - expect(keys.length).to.be(1); - var tile = loadedTilesByZ['1']['1/0/0']; - expect(tile).to.be.a(ol.Tile); - expect(tile.state).to.be(ol.TileState.LOADED); - }); - - it('returns true when all tiles are already loaded', function() { - // a source with no loaded tiles - var source = new ol.test.source.TileMock({ - '1/0/0': true, - '1/0/1': true, - '1/1/0': true, - '1/1/1': true - }); - - var loadedTilesByZ = {}; - var grid = source.getTileGrid(); - var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 1); - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - var loaded = source.findLoadedTiles( - loadedTilesByZ, getTileIfLoaded, 1, range); - expect(loaded).to.be(true); - }); - - it('returns true when all tiles are already loaded (part 2)', function() { - // a source with no loaded tiles + it('does not call getTile() if no tiles are loaded', function() { var source = new ol.test.source.TileMock({}); - - var loadedTilesByZ = { - '1': { - '1/0/0': true, - '1/0/1': true, - '1/1/0': true, - '1/1/1': true, - '1/1/2': true - } - }; + sinon.spy(source, 'getTile'); var grid = source.getTileGrid(); var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 1); + var zoom = 3; + var range = grid.getTileRangeForExtentAndZ(extent, zoom); - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - var loaded = source.findLoadedTiles( - loadedTilesByZ, getTileIfLoaded, 1, range); - expect(loaded).to.be(true); + source.forEachLoadedTile(zoom, range, callback); + expect(source.getTile.callCount).to.be(0); + source.getTile.restore(); }); - it('returns false when all tiles are already loaded', function() { - // a source with no loaded tiles + + it('calls callback for each loaded tile', function() { var source = new ol.test.source.TileMock({ - '1/0/0': true, - '1/0/1': true, - '1/1/0': true, - '1/1/1': false + '1/0/0': ol.TileState.LOADED, + '1/0/1': ol.TileState.LOADED, + '1/1/0': ol.TileState.LOADING, + '1/1/1': ol.TileState.LOADED }); - var loadedTilesByZ = {}; - var grid = source.getTileGrid(); - var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 1); + var zoom = 1; + var range = new ol.TileRange(0, 1, 0, 1); - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - var loaded = source.findLoadedTiles( - loadedTilesByZ, getTileIfLoaded, 1, range); - expect(loaded).to.be(false); + source.forEachLoadedTile(zoom, range, callback); + expect(callback.callCount).to.be(3); }); - it('returns false when all tiles are already loaded (part 2)', function() { + it('returns true if range is fully loaded', function() { // a source with no loaded tiles - var source = new ol.test.source.TileMock({}); + var source = new ol.test.source.TileMock({ + '1/0/0': ol.TileState.LOADED, + '1/0/1': ol.TileState.LOADED, + '1/1/0': ol.TileState.LOADED, + '1/1/1': ol.TileState.LOADED + }); - var loadedTilesByZ = { - '1': { - '1/0/0': true, - '1/0/1': true, - '1/1/0': true, - '1/1/1': false - } - }; - var grid = source.getTileGrid(); - var extent = [-180, -180, 180, 180]; - var range = grid.getTileRangeForExtentAndZ(extent, 1); + var zoom = 1; + var range = new ol.TileRange(0, 1, 0, 1); - function getTileIfLoaded(z, x, y) { - var tile = source.getTile(z, x, y); - return (!goog.isNull(tile) && tile.getState() === ol.TileState.LOADED) ? - tile : null; - } - var loaded = source.findLoadedTiles( - loadedTilesByZ, getTileIfLoaded, 1, range); - expect(loaded).to.be(false); + var covered = source.forEachLoadedTile(zoom, range, function() { + return true; + }); + expect(covered).to.be(true); + }); + + it('returns false if range is not fully loaded', function() { + // a source with no loaded tiles + var source = new ol.test.source.TileMock({ + '1/0/0': ol.TileState.LOADED, + '1/0/1': ol.TileState.LOADED, + '1/1/0': ol.TileState.LOADING, + '1/1/1': ol.TileState.LOADED + }); + + var zoom = 1; + var range = new ol.TileRange(0, 1, 0, 1); + + var covered = source.forEachLoadedTile(zoom, range, function() { + return true; + }); + expect(covered).to.be(false); + }); + + it('allows callback to override loaded check', function() { + // a source with no loaded tiles + var source = new ol.test.source.TileMock({ + '1/0/0': ol.TileState.LOADED, + '1/0/1': ol.TileState.LOADED, + '1/1/0': ol.TileState.LOADED, + '1/1/1': ol.TileState.LOADED + }); + + var zoom = 1; + var range = new ol.TileRange(0, 1, 0, 1); + + var covered = source.forEachLoadedTile(zoom, range, function() { + return false; + }); + expect(covered).to.be(false); }); }); @@ -196,9 +125,10 @@ describe('ol.source.Tile', function() { * * @constructor * @extends {ol.source.Tile} - * @param {Object.} loaded Lookup of already loaded tiles. + * @param {Object.} tileStates Lookup of tile key to + * tile state. */ -ol.test.source.TileMock = function(loaded) { +ol.test.source.TileMock = function(tileStates) { var tileGrid = new ol.tilegrid.TileGrid({ resolutions: [360 / 256, 180 / 256, 90 / 256, 45 / 256], origin: [-180, -180], @@ -210,11 +140,9 @@ ol.test.source.TileMock = function(loaded) { tileGrid: tileGrid }); - /** - * @type {Object.} - * @private - */ - this.loaded_ = loaded; + for (var key in tileStates) { + this.tileCache.set(key, new ol.Tile(key.split('/'), tileStates[key])); + } }; goog.inherits(ol.test.source.TileMock, ol.source.Tile); @@ -224,9 +152,14 @@ goog.inherits(ol.test.source.TileMock, ol.source.Tile); * @inheritDoc */ ol.test.source.TileMock.prototype.getTile = function(z, x, y) { - var key = ol.tilecoord.getKeyZXY(z, x, y); - var tileState = this.loaded_[key] ? ol.TileState.LOADED : ol.TileState.IDLE; - return new ol.Tile([z, x, y], tileState); + var key = this.getKeyZXY(z, x, y); + if (this.tileCache.containsKey(key)) { + return /** @type {!ol.Tile} */ (this.tileCache.get(key)); + } else { + var tile = new ol.Tile(key, ol.TileState.IDLE); + this.tileCache.set(key, tile); + return tile; + } }; @@ -243,8 +176,8 @@ describe('ol.test.source.TileMock', function() { describe('#getTile()', function() { it('returns a tile with state based on constructor arg', function() { var source = new ol.test.source.TileMock({ - '0/0/0': true, - '1/0/0': true + '0/0/0': ol.TileState.LOADED, + '1/0/0': ol.TileState.LOADED }); var tile; @@ -270,9 +203,9 @@ describe('ol.test.source.TileMock', function() { goog.require('goog.object'); goog.require('ol.Tile'); +goog.require('ol.TileRange'); goog.require('ol.TileState'); goog.require('ol.proj'); goog.require('ol.source.Source'); goog.require('ol.source.Tile'); -goog.require('ol.tilecoord'); goog.require('ol.tilegrid.TileGrid');