diff --git a/lib/app.js b/lib/app.js index 9192d4e..6f9e463 100644 --- a/lib/app.js +++ b/lib/app.js @@ -18,7 +18,7 @@ var tessera = require("./index"); debug = debug("tessera"); var FLOAT_PATTERN = "[+-]?(?:\\d+|\\d+\.?\\d+)"; -var SCALE_PATTERN = "@[23]x"; +var SCALE_PATTERN = "@(?:\\d+|\\d+\.?\\d+)x"; // TODO a more complete implementation of this exists...somewhere var getExtension = function(format) { @@ -33,7 +33,7 @@ var getExtension = function(format) { }; var getScale = function(scale) { - return (scale || "@1x").slice(1, 2) | 0; + return parseFloat((scale || "@1x").slice(1)); }; var normalizeHeaders = function(headers) { @@ -121,18 +121,50 @@ module.exports = function(tilelive, options) { 1: uri }; - [2, 3].forEach(function(scale) { - var retinaURI = clone(uri); + // We cache 100 sourceURIs, randomly evict when over limit + var sourceURIsCacheKeys = []; + var sourceURIsCacheSizeLimit = 100; + + var makeScaledSourceURI = function(scale, permanent) { + var retinaURI = clone(uri), + randomIndex; retinaURI.query.scale = scale; // explicitly tell tilelive-mapnik to use larger tiles - retinaURI.query.tileSize = scale * 256; - + retinaURI.query.tileSize = (scale * 256) | 0; + + if (!permanent) { + // Save the URI to the uri cache, but limit its size + while (sourceURIsCacheKeys.length > sourceURIsCacheSizeLimit) { + // Delete random sourceURI + randomIndex = Math.floor(Math.random()*sourceURIsCacheKeys.length); + delete sourceURIs[sourceURIsCacheKeys[randomIndex]]; + sourceURIsCacheKeys.splice(randomIndex, 1); + } + sourceURIsCacheKeys.push(scale); + } sourceURIs[scale] = retinaURI; + + return retinaURI; + }; + + // make scaled source urls for retina @2x and @3x + [2, 3].forEach(function(scale) { + // these are not added to sourceURIsCacheKeys so that they are not ever removed from the cache + makeScaledSourceURI(scale, true); }); + var getSourceURI = function(scale) { + if (scale in sourceURIs) { + return sourceURIs[scale]; + } else { + // scaled uri does not exist so we make one + return makeScaledSourceURI(scale); + } + }; + var getTile = function(z, x, y, scale, format, callback) { - var sourceURI = sourceURIs[scale], + var sourceURI = getSourceURI(scale), params = { tile: { zoom: z,