From 6600435378ddde1af1d84c7ccfd5b7555ab0ac55 Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Tue, 5 Mar 2013 15:29:47 +0100 Subject: [PATCH 01/10] Remove dangling whitespace. --- test/phantom-jasmine/console-runner.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/phantom-jasmine/console-runner.js b/test/phantom-jasmine/console-runner.js index fcd4a6d47f..b86817bd64 100644 --- a/test/phantom-jasmine/console-runner.js +++ b/test/phantom-jasmine/console-runner.js @@ -1,9 +1,9 @@ /** - Jasmine Reporter that outputs test results to the browser console. + Jasmine Reporter that outputs test results to the browser console. Useful for running in a headless environment such as PhantomJs, ZombieJs etc. Usage: - // From your html file that loads jasmine: + // From your html file that loads jasmine: jasmine.getEnv().addReporter(new jasmine.ConsoleReporter()); jasmine.getEnv().execute(); */ @@ -23,7 +23,7 @@ var color_code = this.color_map[color]; return "\033[" + color_code + "m" + text + "\033[0m"; } - + var ConsoleReporter = function() { if (!console || !console.log) { throw "console isn't present!"; } this.status = this.statuses.stopped; From 2c1fa61078442e9ca13e4ec8a4e7ae612757cfde Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Tue, 5 Mar 2013 15:30:01 +0100 Subject: [PATCH 02/10] Nicer output of console runner. --- test/phantom-jasmine/console-runner.js | 61 +++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/test/phantom-jasmine/console-runner.js b/test/phantom-jasmine/console-runner.js index b86817bd64..323e4cda2e 100644 --- a/test/phantom-jasmine/console-runner.js +++ b/test/phantom-jasmine/console-runner.js @@ -86,12 +86,69 @@ } }; + /** + * Will hold the title of the current 'group'. + */ + proto.lastTitle = ""; + + /** + * Pads given string up to a target length with a given character on either + * the left or right side. + */ + proto.pad = function(str, len, char, side){ + var str = str + "", + whichSide = side || 'left', + buff = "", + padChar = char || " ", + padded = "", + iterEnd = len - str.length; + + while(buff.length < iterEnd) { + buff += padChar; + } + if (side === 'left') { + padded = buff + str; + } else { + padded = str + buff; + } + // we still need a substring when we are called with e.g. " . " as char. + return padded.substring(0, len); + } + + /** + * Pads given string up to a target length with a given character on the right + * side. + */ + proto.padRight = function(str, len, char){ + return this.pad(str, len, char, 'right'); + } + + /** + * Pads given string up to a target length with a given character on the right + * side. + */ + proto.padLeft = function(str, len, char){ + return this.pad(str, len, char, 'left'); + } + proto.reportSuiteResults = function(suite) { if (!suite.parentSuite) { return; } + // determine title from full name (wo/ own description) + var title = suite.getFullName().replace(new RegExp(suite.description + "$"), ""); + if (this.lastTitle !== title) { + // when title differs, we have a new 'group' + this.log("\n" + title); + } + // always set current title + this.lastTitle = title; + var results = suite.results(); var failed = results.totalCount - results.passedCount; - var color = (failed > 0)? "red" : "green"; - this.log(suite.description + ": " + results.passedCount + " of " + results.totalCount + " passed.", color); + var color = (failed > 0) ? "red" : "green"; + var logStr = " " + this.padRight(suite.description + " ", 60, '.') + + this.padLeft(results.passedCount, 4) + "/" + + this.padRight(results.totalCount, 4) + " ok"; + this.log(logStr, color); }; proto.log = function(str, color) { From aed6e4c1e368863b3d09e647f5ab026e6ef38f44 Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Tue, 5 Mar 2013 16:05:07 +0100 Subject: [PATCH 03/10] JSHintified, thanks @elemoine. --- test/phantom-jasmine/console-runner.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/phantom-jasmine/console-runner.js b/test/phantom-jasmine/console-runner.js index 323e4cda2e..f94de20aa3 100644 --- a/test/phantom-jasmine/console-runner.js +++ b/test/phantom-jasmine/console-runner.js @@ -13,16 +13,16 @@ throw "jasmine library isn't loaded!"; } - var ANSI = {} + var ANSI = {}; ANSI.color_map = { "green" : 32, "red" : 31 - } + }; ANSI.colorize_text = function(text, color) { var color_code = this.color_map[color]; return "\033[" + color_code + "m" + text + "\033[0m"; - } + }; var ConsoleReporter = function() { if (!console || !console.log) { throw "console isn't present!"; } @@ -79,7 +79,7 @@ var resultText = spec.suite.description + " : " + spec.description; this.log(resultText, "red"); - var items = spec.results().getItems() + var items = spec.results().getItems(); for (var i = 0; i < items.length; i++) { var trace = items[i].trace.stack || items[i].trace; this.log(trace, "red"); @@ -95,8 +95,8 @@ * Pads given string up to a target length with a given character on either * the left or right side. */ - proto.pad = function(str, len, char, side){ - var str = str + "", + proto.pad = function(string, len, char, side){ + var str = string + "", whichSide = side || 'left', buff = "", padChar = char || " ", @@ -113,7 +113,7 @@ } // we still need a substring when we are called with e.g. " . " as char. return padded.substring(0, len); - } + }; /** * Pads given string up to a target length with a given character on the right @@ -121,7 +121,7 @@ */ proto.padRight = function(str, len, char){ return this.pad(str, len, char, 'right'); - } + }; /** * Pads given string up to a target length with a given character on the right @@ -129,7 +129,7 @@ */ proto.padLeft = function(str, len, char){ return this.pad(str, len, char, 'left'); - } + }; proto.reportSuiteResults = function(suite) { if (!suite.parentSuite) { return; } @@ -152,8 +152,8 @@ }; proto.log = function(str, color) { - var text = (color != undefined)? ANSI.colorize_text(str, color) : str; - console.log(text) + var text = (color)? ANSI.colorize_text(str, color) : str; + console.log(text); }; jasmine.ConsoleReporter = ConsoleReporter; From fd6aaff2f5d7d1c9e448e345d6291d311822de53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 16:04:01 +0100 Subject: [PATCH 04/10] Remove listeners when dropping tiles --- src/ol/tile.js | 7 +++++++ src/ol/tilequeue.js | 9 +++++++++ test/spec/ol/tilequeue.test.js | 27 +++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ol/tile.js b/src/ol/tile.js index c9cf6bed73..ce00f9a1db 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -28,6 +28,13 @@ ol.Tile = function(tileCoord) { goog.base(this); + /** + * A count incremented each time the tile is inQueue in a tile queue, + * and decremented each time the tile is dequeued from a tile queue. + * @type {number} + */ + this.inQueue = 0; + /** * @type {ol.TileCoord} */ diff --git a/src/ol/tilequeue.js b/src/ol/tilequeue.js index c5788df972..7e20822308 100644 --- a/src/ol/tilequeue.js +++ b/src/ol/tilequeue.js @@ -89,6 +89,8 @@ ol.TileQueue.prototype.dequeue_ = function() { } var tileKey = tile.getKey(); delete this.queuedTileKeys_[tileKey]; + tile.inQueue--; + goog.asserts.assert(tile.inQueue >= 0); return tile; }; @@ -110,6 +112,8 @@ ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) { this.heap_.push([priority, tile, tileSourceKey, tileCenter]); this.queuedTileKeys_[tileKey] = true; this.siftDown_(0, this.heap_.length - 1); + tile.inQueue++; + goog.asserts.assert(tile.inQueue > 0); } } }; @@ -246,6 +250,11 @@ ol.TileQueue.prototype.reprioritize = function() { if (priority == ol.TileQueue.DROP) { tileKey = tile.getKey(); delete this.queuedTileKeys_[tileKey]; + tile.inQueue--; + goog.asserts.assert(tile.inQueue >= 0); + if (tile.inQueue === 0) { + goog.events.removeAll(tile); + } } else { node[0] = priority; heap[n++] = node; diff --git a/test/spec/ol/tilequeue.test.js b/test/spec/ol/tilequeue.test.js index 3ca38a2981..57db2b2f8c 100644 --- a/test/spec/ol/tilequeue.test.js +++ b/test/spec/ol/tilequeue.test.js @@ -21,13 +21,20 @@ describe('ol.TileQueue', function() { } function addRandomPriorityTiles(tq, num) { + var tiles = []; var i, tile, priority; for (i = 0; i < num; i++) { tile = new ol.Tile(); + tile.toDrop = (i % 2 === 0) ? true : false; + goog.events.listen(tile, goog.events.EventType.CHANGE, + goog.nullFunction); priority = Math.floor(Math.random() * 100); tq.heap_.push([priority, tile, '', new ol.Coordinate(0, 0)]); tq.queuedTileKeys_[tile.getKey()] = true; + tile.inQueue++; + tiles.push(tile); } + return tiles; } describe('heapify', function() { @@ -45,16 +52,15 @@ describe('ol.TileQueue', function() { it('does reprioritize the array', function() { var tq = new ol.TileQueue(function() {}); - addRandomPriorityTiles(tq, 100); + var tiles = addRandomPriorityTiles(tq, 100); tq.heapify_(); // now reprioritize, changing the priority of 50 tiles and removing the // rest - var i = 0; - tq.tilePriorityFunction_ = function() { - if ((i++) % 2 === 0) { + tq.tilePriorityFunction_ = function(tile) { + if (tile.toDrop) { return ol.TileQueue.DROP; } return Math.floor(Math.random() * 100); @@ -64,10 +70,23 @@ describe('ol.TileQueue', function() { expect(tq.heap_.length).toEqual(50); expect(isHeap(tq)).toBeTruthy(); + var i, tile; + for (i = 0; i < tiles.length; ++i) { + tile = tiles[i]; + var hasListener = goog.events.hasListener(tile); + if (tile.toDrop) { + expect(hasListener).toBeFalsy(); + } else { + expect(hasListener).toBeTruthy(); + } + } + }); }); }); +goog.require('goog.events'); +goog.require('goog.events.EventType'); goog.require('ol.Coordinate'); goog.require('ol.Tile'); goog.require('ol.TileQueue'); From 4e758f87aef7def99b7187c6e846fa9bea754ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 16:41:06 +0100 Subject: [PATCH 05/10] Do not register multiple listeners on same tile --- .../canvas/canvastilelayerrenderer.js | 3 +-- src/ol/renderer/dom/domtilelayerrenderer.js | 3 +-- src/ol/renderer/layerrenderer.js | 26 +++++++++++++++++-- .../renderer/webgl/webgltilelayerrenderer.js | 3 +-- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 1374457df6..216625d560 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -158,8 +158,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index afe7463db1..da2dd226a8 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -116,8 +116,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 6a6f1d4aff..736afc0605 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -40,6 +40,12 @@ ol.renderer.Layer = function(mapRenderer, layer) { */ this.layer_ = layer; + /** + * @protected + * @type {Object.} + */ + this.observedTileKeys = {}; + goog.events.listen(this.layer_, ol.Object.getChangedEventType(ol.layer.LayerProperty.BRIGHTNESS), this.handleLayerBrightnessChange, false, this); @@ -167,13 +173,29 @@ ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { /** * Handle changes in tile state. * @param {goog.events.Event} event Tile change event. - * @protected + * @private */ -ol.renderer.Layer.prototype.handleTileChange = function(event) { +ol.renderer.Layer.prototype.handleTileChange_ = function(event) { var tile = /** @type {ol.Tile} */ (event.target); if (tile.getState() === ol.TileState.LOADED) { this.getMap().requestRenderFrame(); } + delete this.observedTileKeys[tile.getKey()]; +}; + + +/** + * Listen once to titileKey, le change event. + * @param {ol.Tile} tile Tile. + * @protected + */ +ol.renderer.Layer.prototype.listenToTileChange = function(tile) { + var tileKey = tile.getKey(); + if (!(tileKey in this.observedTileKeys)) { + this.observedTileKeys[tileKey] = true; + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, + this.handleTileChange_, false, this); + } }; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 4059509e0a..0058746bab 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -391,8 +391,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); From a4afcd533fce7d577a9aae75bf8351e87009b126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 18:06:57 +0100 Subject: [PATCH 06/10] Add FIXME --- src/ol/tile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ol/tile.js b/src/ol/tile.js index ce00f9a1db..6b8956352b 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -1,3 +1,5 @@ +// FIXME should inQueue be private? + goog.provide('ol.Tile'); goog.provide('ol.TileState'); From 59271ae2d8dc9b3bf57aebb3fac9a85810c8911e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 18:35:21 +0100 Subject: [PATCH 07/10] Fix typo (thanks @bbinet) --- src/ol/renderer/layerrenderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 736afc0605..a0a8f4b932 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -185,7 +185,7 @@ ol.renderer.Layer.prototype.handleTileChange_ = function(event) { /** - * Listen once to titileKey, le change event. + * Listen once to tileKey, le change event. * @param {ol.Tile} tile Tile. * @protected */ From 7d1db4883603461bdf918d9fbcfe61b3267dcfca Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 6 Mar 2013 01:57:06 +0100 Subject: [PATCH 08/10] Find proj4js projection even if code is different than srs. --- src/ol/projection.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ol/projection.js b/src/ol/projection.js index bf6586e7ee..ad48201ad8 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -410,7 +410,12 @@ ol.projection.getProj4jsProjectionFromCode_ = function(code) { var proj4jsProjection = proj4jsProjections[code]; if (!goog.isDef(proj4jsProjection)) { var proj4jsProj = new Proj4js.Proj(code); - proj4jsProjection = new ol.Proj4jsProjection_(code, proj4jsProj); + var srsCode = proj4jsProj.srsCode; + proj4jsProjection = proj4jsProjections[srsCode]; + if (!goog.isDef(proj4jsProjection)) { + proj4jsProjection = new ol.Proj4jsProjection_(srsCode, proj4jsProj); + proj4jsProjections[srsCode] = proj4jsProjection; + } proj4jsProjections[code] = proj4jsProjection; } return proj4jsProjection; From f1b72a10bc73db5bab9f35a37d090447dbea05c1 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 6 Mar 2013 01:59:35 +0100 Subject: [PATCH 09/10] Tests for cached proj4js projections. --- test/spec/ol/projection.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/spec/ol/projection.test.js b/test/spec/ol/projection.test.js index c961d41819..34e87ca0b3 100644 --- a/test/spec/ol/projection.test.js +++ b/test/spec/ol/projection.test.js @@ -144,6 +144,22 @@ describe('ol.projection', function() { expect(point.y).toRoughlyEqual(200146.976, 1); }); + it('caches the new Proj4js projections given their srsCode', function() { + Proj4js.defs['EPSG:21781'] = + '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 ' + + '+k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' + + '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs'; + var code = 'urn:ogc:def:crs:EPSG:21781'; + var srsCode = 'EPSG:21781'; + var proj = ol.projection.getFromCode(code); + expect(ol.projection.proj4jsProjections_.hasOwnProperty(code)) + .toBeTruthy(); + expect(ol.projection.proj4jsProjections_.hasOwnProperty(srsCode)) + .toBeTruthy(); + var proj2 = ol.projection.getFromCode(srsCode); + expect(proj2).toBe(proj); + }); + it('numerically estimates point scale at the equator', function() { var googleProjection = ol.projection.getFromCode('GOOGLE'); expect(googleProjection.getPointResolution(1, new ol.Coordinate(0, 0))). From bb1cf45c0ae4b6c4891ab59b6f5c15cbd1af0f73 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 6 Mar 2013 02:38:03 +0100 Subject: [PATCH 10/10] Add Proj4js.Proj.srsCode property to Proj4js externs --- externs/proj4js.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/externs/proj4js.js b/externs/proj4js.js index 0dd711eb63..ebdf9566da 100644 --- a/externs/proj4js.js +++ b/externs/proj4js.js @@ -70,6 +70,12 @@ Proj4js.Proj.prototype.title; Proj4js.Proj.prototype.units; +/** + * @type {string} + */ +Proj4js.Proj.prototype.srsCode; + + /** * @nosideeffects * @param {Proj4js.Proj} source