From 1e12e7ca906cee3bd7df2fe91a74f9d6b0c3441f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Fri, 21 Nov 2014 10:21:40 +0100 Subject: [PATCH] =?UTF-8?q?Remove=20unused=20WebGL=C2=A0related=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ol/structs/buffer.js | 203 +------- src/ol/structs/integerset.js | 330 ------------- src/ol/webgl/context.js | 35 +- test/spec/ol/structs/buffer.test.js | 242 --------- test/spec/ol/structs/integerset.test.js | 622 ------------------------ 5 files changed, 14 insertions(+), 1418 deletions(-) delete mode 100644 src/ol/structs/integerset.js delete mode 100644 test/spec/ol/structs/integerset.test.js diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index 29ddb99b56..7faf1a4029 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -1,10 +1,8 @@ goog.provide('ol.structs.Buffer'); goog.require('goog.array'); -goog.require('goog.asserts'); goog.require('goog.webgl'); goog.require('ol'); -goog.require('ol.structs.IntegerSet'); /** @@ -21,11 +19,10 @@ ol.structs.BufferUsage = { /** * @constructor * @param {Array.=} opt_arr Array. - * @param {number=} opt_used Used. * @param {number=} opt_usage Usage. * @struct */ -ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { +ol.structs.Buffer = function(opt_arr, opt_usage) { /** * @private @@ -33,43 +30,6 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { */ this.arr_ = goog.isDef(opt_arr) ? opt_arr : []; - /** - * @private - * @type {Array.} - */ - this.dirtySets_ = []; - - /** - * @private - * @type {ol.structs.IntegerSet} - */ - this.freeSet_ = new ol.structs.IntegerSet(); - - var used = goog.isDef(opt_used) ? opt_used : this.arr_.length; - if (used < this.arr_.length) { - this.freeSet_.addRange(used, this.arr_.length); - } - if (ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS) { - var arr = this.arr_; - var n = arr.length; - var i; - for (i = used; i < n; ++i) { - arr[i] = NaN; - } - } - - /** - * @private - * @type {?Float32Array} - */ - this.split32_ = null; - - /** - * @private - * @type {ol.structs.IntegerSet} - */ - this.split32DirtySet_ = null; - /** * @private * @type {number} @@ -80,56 +40,6 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { }; -/** - * @param {number} size Size. - * @return {number} Offset. - */ -ol.structs.Buffer.prototype.allocate = function(size) { - goog.asserts.assert(size > 0); - var offset = this.freeSet_.findRange(size); - goog.asserts.assert(offset != -1); // FIXME - this.freeSet_.removeRange(offset, offset + size); - return offset; -}; - - -/** - * @param {Array.} values Values. - * @return {number} Offset. - */ -ol.structs.Buffer.prototype.add = function(values) { - var size = values.length; - var offset = this.allocate(size); - var i; - for (i = 0; i < size; ++i) { - this.arr_[offset + i] = values[i]; - } - this.markDirty(size, offset); - return offset; -}; - - -/** - * @param {ol.structs.IntegerSet} dirtySet Dirty set. - */ -ol.structs.Buffer.prototype.addDirtySet = function(dirtySet) { - goog.asserts.assert(!goog.array.contains(this.dirtySets_, dirtySet)); - this.dirtySets_.push(dirtySet); -}; - - -/** - * @param {function(this: T, number, number)} f Callback. - * @param {T=} opt_this The object to use as `this` in `f`. - * @template T - */ -ol.structs.Buffer.prototype.forEachRange = function(f, opt_this) { - if (this.arr_.length !== 0) { - this.freeSet_.forEachRangeInverted(0, this.arr_.length, f, opt_this); - } -}; - - /** * @return {Array.} Array. */ @@ -138,120 +48,9 @@ ol.structs.Buffer.prototype.getArray = function() { }; -/** - * @return {number} Count. - */ -ol.structs.Buffer.prototype.getCount = function() { - return this.arr_.length - this.freeSet_.getSize(); -}; - - -/** - * @return {ol.structs.IntegerSet} Free set. - */ -ol.structs.Buffer.prototype.getFreeSet = function() { - return this.freeSet_; -}; - - -/** - * Returns a Float32Array twice the length of the buffer containing each value - * split into two 32-bit floating point values that, when added together, - * approximate the original value. Even indicies contain the high bits, odd - * indicies contain the low bits. - * @see http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/ - * @return {Float32Array} Split. - */ -ol.structs.Buffer.prototype.getSplit32 = function() { - var arr = this.arr_; - var n = arr.length; - if (goog.isNull(this.split32DirtySet_)) { - this.split32DirtySet_ = new ol.structs.IntegerSet([0, n]); - this.addDirtySet(this.split32DirtySet_); - } - if (goog.isNull(this.split32_)) { - this.split32_ = new Float32Array(2 * n); - } - var split32 = this.split32_; - this.split32DirtySet_.forEachRange(function(start, stop) { - var doubleHigh, i, j, value; - for (i = start, j = 2 * start; i < stop; ++i, j += 2) { - value = arr[i]; - if (value < 0) { - doubleHigh = 65536 * Math.floor(-value / 65536); - split32[j] = -doubleHigh; - split32[j + 1] = value + doubleHigh; - } else { - doubleHigh = 65536 * Math.floor(value / 65536); - split32[j] = doubleHigh; - split32[j + 1] = value - doubleHigh; - } - } - }); - this.split32DirtySet_.clear(); - return this.split32_; -}; - - /** * @return {number} Usage. */ ol.structs.Buffer.prototype.getUsage = function() { return this.usage_; }; - - -/** - * @param {number} size Size. - * @param {number} offset Offset. - */ -ol.structs.Buffer.prototype.markDirty = function(size, offset) { - var i, ii; - for (i = 0, ii = this.dirtySets_.length; i < ii; ++i) { - this.dirtySets_[i].addRange(offset, offset + size); - } -}; - - -/** - * @param {number} size Size. - * @param {number} offset Offset. - */ -ol.structs.Buffer.prototype.remove = function(size, offset) { - var i, ii; - this.freeSet_.addRange(offset, offset + size); - for (i = 0, ii = this.dirtySets_.length; i < ii; ++i) { - this.dirtySets_[i].removeRange(offset, offset + size); - } - if (ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS) { - var arr = this.arr_; - for (i = 0; i < size; ++i) { - arr[offset + i] = NaN; - } - } -}; - - -/** - * @param {ol.structs.IntegerSet} dirtySet Dirty set. - */ -ol.structs.Buffer.prototype.removeDirtySet = function(dirtySet) { - var removed = goog.array.remove(this.dirtySets_, dirtySet); - goog.asserts.assert(removed); -}; - - -/** - * @param {Array.} values Values. - * @param {number} offset Offset. - */ -ol.structs.Buffer.prototype.set = function(values, offset) { - var arr = this.arr_; - var n = values.length; - goog.asserts.assert(0 <= offset && offset + n <= arr.length); - var i; - for (i = 0; i < n; ++i) { - arr[offset + i] = values[i]; - } - this.markDirty(n, offset); -}; diff --git a/src/ol/structs/integerset.js b/src/ol/structs/integerset.js deleted file mode 100644 index de716c6842..0000000000 --- a/src/ol/structs/integerset.js +++ /dev/null @@ -1,330 +0,0 @@ -goog.provide('ol.structs.IntegerSet'); - -goog.require('goog.asserts'); - - - -/** - * A set of integers represented as a set of integer ranges. - * This implementation is designed for the case when the number of distinct - * integer ranges is small. - * @constructor - * @struct - * @param {Array.=} opt_arr Array. - */ -ol.structs.IntegerSet = function(opt_arr) { - - /** - * @private - * @type {Array.} - */ - this.arr_ = goog.isDef(opt_arr) ? opt_arr : []; - - if (goog.DEBUG) { - this.assertValid(); - } - -}; - - -/** - * @param {number} addStart Start. - * @param {number} addStop Stop. - */ -ol.structs.IntegerSet.prototype.addRange = function(addStart, addStop) { - goog.asserts.assert(addStart <= addStop); - if (addStart == addStop) { - return; - } - var arr = this.arr_; - var n = arr.length; - var i; - for (i = 0; i < n; i += 2) { - if (addStart <= arr[i]) { - // FIXME check if splice is really needed - arr.splice(i, 0, addStart, addStop); - this.compactRanges_(); - return; - } - } - arr.push(addStart, addStop); - this.compactRanges_(); -}; - - -/** - * FIXME empty description for jsdoc - */ -ol.structs.IntegerSet.prototype.assertValid = function() { - var arr = this.arr_; - var n = arr.length; - goog.asserts.assert(n % 2 === 0); - var i; - for (i = 1; i < n; ++i) { - goog.asserts.assert(arr[i] > arr[i - 1]); - } -}; - - -/** - * FIXME empty description for jsdoc - */ -ol.structs.IntegerSet.prototype.clear = function() { - this.arr_.length = 0; -}; - - -/** - * @private - */ -ol.structs.IntegerSet.prototype.compactRanges_ = function() { - var arr = this.arr_; - var n = arr.length; - var rangeIndex = 0; - var i; - for (i = 0; i < n; i += 2) { - if (arr[i] == arr[i + 1]) { - // pass - } else if (rangeIndex > 0 && - arr[rangeIndex - 2] <= arr[i] && - arr[i] <= arr[rangeIndex - 1]) { - arr[rangeIndex - 1] = Math.max(arr[rangeIndex - 1], arr[i + 1]); - } else { - arr[rangeIndex++] = arr[i]; - arr[rangeIndex++] = arr[i + 1]; - } - } - arr.length = rangeIndex; -}; - - -/** - * Finds the start of smallest range that is at least of length minSize, or -1 - * if no such range exists. - * @param {number} minSize Minimum size. - * @return {number} Index. - */ -ol.structs.IntegerSet.prototype.findRange = function(minSize) { - goog.asserts.assert(minSize > 0); - var arr = this.arr_; - var n = arr.length; - var bestIndex = -1; - var bestSize, i, size; - for (i = 0; i < n; i += 2) { - size = arr[i + 1] - arr[i]; - if (size == minSize) { - return arr[i]; - } else if (size > minSize && (bestIndex == -1 || size < bestSize)) { - bestIndex = arr[i]; - bestSize = size; - } - } - return bestIndex; -}; - - -/** - * Calls f with each integer range. - * @param {function(this: T, number, number)} f Callback. - * @param {T=} opt_this The object to use as `this` in `f`. - * @template T - */ -ol.structs.IntegerSet.prototype.forEachRange = function(f, opt_this) { - var arr = this.arr_; - var n = arr.length; - var i; - for (i = 0; i < n; i += 2) { - f.call(opt_this, arr[i], arr[i + 1]); - } -}; - - -/** - * Calls f with each integer range not in [start, stop) - 'this'. - * @param {number} start Start. - * @param {number} stop Stop. - * @param {function(this: T, number, number)} f Callback. - * @param {T=} opt_this The object to use as `this` in `f`. - * @template T - */ -ol.structs.IntegerSet.prototype.forEachRangeInverted = - function(start, stop, f, opt_this) { - goog.asserts.assert(start < stop); - var arr = this.arr_; - var n = arr.length; - if (n === 0) { - f.call(opt_this, start, stop); - } else { - if (start < arr[0]) { - f.call(opt_this, start, arr[0]); - } - var i; - for (i = 1; i < n - 1; i += 2) { - f.call(opt_this, arr[i], arr[i + 1]); - } - if (arr[n - 1] < stop) { - f.call(opt_this, arr[n - 1], stop); - } - } -}; - - -/** - * @return {Array.} Array. - */ -ol.structs.IntegerSet.prototype.getArray = function() { - return this.arr_; -}; - - -/** - * Returns the first element in the set, or -1 if the set is empty. - * @return {number} Start. - */ -ol.structs.IntegerSet.prototype.getFirst = function() { - return this.arr_.length === 0 ? -1 : this.arr_[0]; -}; - - -/** - * Returns the first integer after the last element in the set, or -1 if the - * set is empty. - * @return {number} Last. - */ -ol.structs.IntegerSet.prototype.getLast = function() { - var n = this.arr_.length; - return n === 0 ? -1 : this.arr_[n - 1]; -}; - - -/** - * Returns the number of integers in the set. - * @return {number} Size. - */ -ol.structs.IntegerSet.prototype.getSize = function() { - var arr = this.arr_; - var n = arr.length; - var size = 0; - var i; - for (i = 0; i < n; i += 2) { - size += arr[i + 1] - arr[i]; - } - return size; -}; - - -/** - * @param {number} start Start. - * @param {number} stop Stop. - * @return {boolean} Intersects range. - */ -ol.structs.IntegerSet.prototype.intersectsRange = function(start, stop) { - goog.asserts.assert(start <= stop); - if (start == stop) { - return false; - } else { - var arr = this.arr_; - var n = arr.length; - var i = 0; - for (i = 0; i < n; i += 2) { - if (arr[i] <= start && start < arr[i + 1] || - arr[i] < stop && stop - 1 < arr[i + 1] || - start < arr[i] && arr[i + 1] <= stop) { - return true; - } - } - return false; - } -}; - - -/** - * @return {boolean} Is empty. - */ -ol.structs.IntegerSet.prototype.isEmpty = function() { - return this.arr_.length === 0; -}; - - -/** - * @return {Array.} Array. - */ -ol.structs.IntegerSet.prototype.pack = function() { - return this.arr_; -}; - - -/** - * @param {number} removeStart Start. - * @param {number} removeStop Stop. - */ -ol.structs.IntegerSet.prototype.removeRange = - function(removeStart, removeStop) { - // FIXME this could be more efficient - goog.asserts.assert(removeStart <= removeStop); - var arr = this.arr_; - var n = arr.length; - var i; - for (i = 0; i < n; i += 2) { - if (removeStop < arr[i] || arr[i + 1] < removeStart) { - continue; - } else if (arr[i] > removeStop) { - break; - } - if (removeStart < arr[i]) { - if (removeStop == arr[i]) { - break; - } else if (removeStop < arr[i + 1]) { - arr[i] = Math.max(arr[i], removeStop); - break; - } else { - arr.splice(i, 2); - i -= 2; - n -= 2; - } - } else if (removeStart == arr[i]) { - if (removeStop < arr[i + 1]) { - arr[i] = removeStop; - break; - } else if (removeStop == arr[i + 1]) { - arr.splice(i, 2); - break; - } else { - arr.splice(i, 2); - i -= 2; - n -= 2; - } - } else { - if (removeStop < arr[i + 1]) { - arr.splice(i, 2, arr[i], removeStart, removeStop, arr[i + 1]); - break; - } else if (removeStop == arr[i + 1]) { - arr[i + 1] = removeStart; - break; - } else { - arr[i + 1] = removeStart; - } - } - } - this.compactRanges_(); -}; - - -if (goog.DEBUG) { - - /** - * @return {string} String. - */ - ol.structs.IntegerSet.prototype.toString = function() { - var arr = this.arr_; - var n = arr.length; - var result = new Array(n / 2); - var resultIndex = 0; - var i; - for (i = 0; i < n; i += 2) { - result[resultIndex++] = arr[i] + '-' + arr[i + 1]; - } - return result.join(', '); - }; - -} diff --git a/src/ol/webgl/context.js b/src/ol/webgl/context.js index 674526eac4..8992692414 100644 --- a/src/ol/webgl/context.js +++ b/src/ol/webgl/context.js @@ -7,14 +7,12 @@ goog.require('goog.log'); goog.require('goog.object'); goog.require('ol.has'); goog.require('ol.structs.Buffer'); -goog.require('ol.structs.IntegerSet'); goog.require('ol.webgl.WebGLContextEventType'); /** * @typedef {{buf: ol.structs.Buffer, - * buffer: WebGLBuffer, - * dirtySet: ol.structs.IntegerSet}} + * buffer: WebGLBuffer}} */ ol.webgl.BufferCacheEntry; @@ -89,6 +87,9 @@ ol.webgl.Context = function(canvas, gl) { /** + * Just bind the buffer if it's in the cache. Otherwise create + * the WebGL buffer, bind it, populate it, and add an entry to + * the cache. * @param {number} target Target. * @param {ol.structs.Buffer} buf Buffer. */ @@ -99,17 +100,6 @@ ol.webgl.Context.prototype.bindBuffer = function(target, buf) { if (bufferKey in this.bufferCache_) { var bufferCacheEntry = this.bufferCache_[bufferKey]; gl.bindBuffer(target, bufferCacheEntry.buffer); - bufferCacheEntry.dirtySet.forEachRange(function(start, stop) { - // FIXME check if slice is really efficient here - var slice = arr.slice(start, stop); - gl.bufferSubData( - target, - start, - target == goog.webgl.ARRAY_BUFFER ? - new Float32Array(slice) : - new Uint16Array(slice)); - }); - bufferCacheEntry.dirtySet.clear(); } else { var buffer = gl.createBuffer(); gl.bindBuffer(target, buffer); @@ -118,12 +108,9 @@ ol.webgl.Context.prototype.bindBuffer = function(target, buf) { target == goog.webgl.ARRAY_BUFFER ? new Float32Array(arr) : new Uint16Array(arr), buf.getUsage()); - var dirtySet = new ol.structs.IntegerSet(); - buf.addDirtySet(dirtySet); this.bufferCache_[bufferKey] = { buf: buf, - buffer: buffer, - dirtySet: dirtySet + buffer: buffer }; } }; @@ -137,7 +124,6 @@ ol.webgl.Context.prototype.deleteBuffer = function(buf) { var bufferKey = goog.getUid(buf); goog.asserts.assert(bufferKey in this.bufferCache_); var bufferCacheEntry = this.bufferCache_[bufferKey]; - bufferCacheEntry.buf.removeDirtySet(bufferCacheEntry.dirtySet); if (!gl.isContextLost()) { gl.deleteBuffer(bufferCacheEntry.buffer); } @@ -149,9 +135,6 @@ ol.webgl.Context.prototype.deleteBuffer = function(buf) { * @inheritDoc */ ol.webgl.Context.prototype.disposeInternal = function() { - goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) { - bufferCacheEntry.buf.removeDirtySet(bufferCacheEntry.dirtySet); - }); var gl = this.getGL(); if (!gl.isContextLost()) { goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) { @@ -185,6 +168,8 @@ ol.webgl.Context.prototype.getGL = function() { /** + * Get shader from the cache if it's in the cache. Otherwise, create + * the WebGL shader, compile it, and add entry to cache. * @param {ol.webgl.Shader} shaderObject Shader object. * @return {WebGLShader} Shader. */ @@ -213,6 +198,9 @@ ol.webgl.Context.prototype.getShader = function(shaderObject) { /** + * Get the program from the cache if it's in the cache. Otherwise create + * the WebGL program, attach the shaders to it, and add an entry to the + * cache. * @param {ol.webgl.shader.Fragment} fragmentShaderObject Fragment shader. * @param {ol.webgl.shader.Vertex} vertexShaderObject Vertex shader. * @return {WebGLProgram} Program. @@ -263,6 +251,9 @@ ol.webgl.Context.prototype.handleWebGLContextRestored = function() { /** + * Just return false if that program is used already. Other use + * that program (call `gl.useProgram`) and make it the "current + * program". * @param {WebGLProgram} program Program. * @return {boolean} Changed. * @api diff --git a/test/spec/ol/structs/buffer.test.js b/test/spec/ol/structs/buffer.test.js index 94d24cec86..454e36ce77 100644 --- a/test/spec/ol/structs/buffer.test.js +++ b/test/spec/ol/structs/buffer.test.js @@ -14,7 +14,6 @@ describe('ol.structs.Buffer', function() { it('constructs an empty instance', function() { expect(b.getArray()).to.be.empty(); - expect(b.getCount()).to.be(0); }); }); @@ -41,16 +40,6 @@ describe('ol.structs.Buffer', function() { b = new ol.structs.Buffer(); }); - describe('forEachRange', function() { - - it('does not call the callback', function() { - var callback = sinon.spy(); - b.forEachRange(callback); - expect(callback).not.to.be.called(); - }); - - }); - describe('getArray', function() { it('returns an empty array', function() { @@ -59,239 +48,8 @@ describe('ol.structs.Buffer', function() { }); - describe('getCount', function() { - - it('returns 0', function() { - expect(b.getCount()).to.be(0); - }); - - }); - - }); - - describe('with an empty instance with spare capacity', function() { - - var b; - beforeEach(function() { - b = new ol.structs.Buffer(new Array(4), 0); - }); - - describe('add', function() { - - it('allows elements to be added', function() { - expect(b.add([0, 1, 2, 3])).to.be(0); - expect(b.getArray()).to.eql([0, 1, 2, 3]); - }); - - }); - - describe('forEachRange', function() { - - it('does not call the callback', function() { - var callback = sinon.spy(); - b.forEachRange(callback); - expect(callback).not.to.be.called(); - }); - - }); - - describe('getCount', function() { - - it('returns 0', function() { - expect(b.getCount()).to.be(0); - }); - - }); - - }); - - describe('with an instance with no spare capacity', function() { - - var b; - beforeEach(function() { - b = new ol.structs.Buffer([0, 1, 2, 3]); - }); - - describe('add', function() { - - it('throws an exception', function() { - expect(function() { - b.add([4, 5]); - }).to.throwException(); - }); - - }); - - describe('forEachRange', function() { - - it('calls the callback', function() { - var callback = sinon.spy(); - b.forEachRange(callback); - expect(callback.calledOnce).to.be(true); - expect(callback.args[0]).to.eql([0, 4]); - }); - - }); - - describe('getCount', function() { - - it('returns the expected value', function() { - expect(b.getCount()).to.be(4); - }); - - }); - - describe('remove', function() { - - it('allows items to be removes', function() { - expect(function() { - b.remove(4, 2); - }).to.not.throwException(); - }); - - }); - - describe('set', function() { - - it('updates the items', function() { - b.set([5, 6], 2); - expect(b.getArray()).to.eql([0, 1, 5, 6]); - }); - - it('marks the set items as dirty', function() { - var dirtySet = new ol.structs.IntegerSet(); - b.addDirtySet(dirtySet); - expect(dirtySet.isEmpty()).to.be(true); - b.set([5, 6], 2); - expect(dirtySet.isEmpty()).to.be(false); - expect(dirtySet.getArray()).to.eql([2, 4]); - }); - - }); - - }); - - describe('with an instance with spare capacity', function() { - - var b; - beforeEach(function() { - var arr = [0, 1, 2, 3]; - arr.length = 8; - b = new ol.structs.Buffer(arr, 4); - }); - - describe('add', function() { - - it('allows more items to be added', function() { - expect(b.add([4, 5, 6, 7])).to.be(4); - expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]); - }); - - }); - - describe('forEachRange', function() { - - it('calls the callback with the expected values', function() { - var callback = sinon.spy(); - b.forEachRange(callback); - expect(callback.calledOnce).to.be(true); - expect(callback.args[0]).to.eql([0, 4]); - }); - - }); - - describe('getCount', function() { - - it('returns the expected value', function() { - expect(b.getCount()).to.be(4); - }); - - }); - - describe('getFreeSet', function() { - - it('returns the expected set', function() { - var freeSet = b.getFreeSet(); - expect(freeSet.isEmpty()).to.be(false); - expect(freeSet.getArray()).to.eql([4, 8]); - }); - - }); - - }); - - describe('with a populated instance', function() { - - var b; - beforeEach(function() { - b = new ol.structs.Buffer([1234567.1234567, -7654321.7654321]); - }); - - describe('getSplit32', function() { - - it('returns the expected value', function() { - var split32 = b.getSplit32(); - expect(split32).to.be.a(Float32Array); - expect(split32).to.have.length(4); - expect(split32[0]).to.roughlyEqual(1179648.0, 1e1); - expect(split32[1]).to.roughlyEqual(54919.12345670001, 1e-2); - expect(split32[2]).to.roughlyEqual(-7602176.0, 1e1); - expect(split32[3]).to.roughlyEqual(-52145.76543209981, 1e-2); - }); - - it('tracks updates', function() { - b.getSplit32(); - b.getArray()[0] = 0; - b.markDirty(1, 0); - var split32 = b.getSplit32(); - expect(split32).to.be.a(Float32Array); - expect(split32).to.have.length(4); - expect(split32[0]).to.be(0); - expect(split32[1]).to.be(0); - expect(split32[2]).to.roughlyEqual(-7602176.0, 1e1); - expect(split32[3]).to.roughlyEqual(-52145.76543209981, 1e-2); - }); - - }); - }); - - describe('usage tests', function() { - - it('allows multiple adds and removes', function() { - var b = new ol.structs.Buffer(new Array(8), 0); - expect(b.add([0, 1])).to.be(0); - expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]); - expect(b.getCount()).to.be(2); - expect(b.add([2, 3, 4, 5])).to.be(2); - expect(b.getArray()).to.arreqlNaN([0, 1, 2, 3, 4, 5, NaN, NaN]); - expect(b.getCount()).to.be(6); - expect(b.add([6, 7])).to.be(6); - expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]); - expect(b.getCount()).to.be(8); - b.remove(2, 2); - expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, 4, 5, 6, 7]); - expect(b.getCount()).to.be(6); - expect(b.add([8, 9])).to.be(2); - expect(b.getArray()).to.eql([0, 1, 8, 9, 4, 5, 6, 7]); - expect(b.getCount()).to.be(8); - b.remove(1, 1); - expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 4, 5, 6, 7]); - expect(b.getCount()).to.be(7); - b.remove(4, 4); - expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, NaN, NaN, NaN, NaN]); - expect(b.getCount()).to.be(3); - expect(b.add([10, 11, 12])).to.be(4); - expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 10, 11, 12, NaN]); - expect(b.getCount()).to.be(6); - expect(b.add([13])).to.be(1); - expect(b.getArray()).to.arreqlNaN([0, 13, 8, 9, 10, 11, 12, NaN]); - expect(b.getCount()).to.be(7); - }); - }); }); - goog.require('ol.structs.Buffer'); -goog.require('ol.structs.IntegerSet'); diff --git a/test/spec/ol/structs/integerset.test.js b/test/spec/ol/structs/integerset.test.js deleted file mode 100644 index 2fb7af18fa..0000000000 --- a/test/spec/ol/structs/integerset.test.js +++ /dev/null @@ -1,622 +0,0 @@ -goog.provide('ol.test.structs.IntegerSet'); - - -describe('ol.structs.IntegerSet', function() { - - describe('constructor', function() { - - describe('without an argument', function() { - - it('constructs an empty instance', function() { - var is = new ol.structs.IntegerSet(); - expect(is).to.be.an(ol.structs.IntegerSet); - expect(is.getArray()).to.be.empty(); - }); - - }); - - describe('with an argument', function() { - - it('constructs with a valid array', function() { - var is = new ol.structs.IntegerSet([0, 2, 4, 6]); - expect(is).to.be.an(ol.structs.IntegerSet); - expect(is.getArray()).to.eql([0, 2, 4, 6]); - }); - - it('throws an exception with an odd number of elements', function() { - expect(function() { - var is = new ol.structs.IntegerSet([0, 2, 4]); - is = is; // suppress gjslint warning about unused variable - }).to.throwException(); - }); - - it('throws an exception with out-of-order elements', function() { - expect(function() { - var is = new ol.structs.IntegerSet([0, 2, 2, 4]); - is = is; // suppress gjslint warning about unused variable - }).to.throwException(); - }); - - }); - - }); - - describe('with an empty instance', function() { - - var is; - beforeEach(function() { - is = new ol.structs.IntegerSet(); - }); - - describe('addRange', function() { - - it('creates a new element', function() { - is.addRange(0, 2); - expect(is.getArray()).to.eql([0, 2]); - }); - - }); - - describe('findRange', function() { - - it('returns -1', function() { - expect(is.findRange(2)).to.be(-1); - }); - - }); - - describe('forEachRange', function() { - - it('does not call the callback', function() { - var callback = sinon.spy(); - is.forEachRange(callback); - expect(callback).to.not.be.called(); - }); - - }); - - describe('forEachRangeInverted', function() { - - it('does call the callback', function() { - var callback = sinon.spy(); - is.forEachRangeInverted(0, 8, callback); - expect(callback.calledOnce).to.be(true); - expect(callback.args[0]).to.eql([0, 8]); - }); - - }); - - describe('getFirst', function() { - - it('returns -1', function() { - expect(is.getFirst()).to.be(-1); - }); - - }); - - describe('getLast', function() { - - it('returns -1', function() { - expect(is.getLast()).to.be(-1); - }); - - }); - - describe('getSize', function() { - - it('returns 0', function() { - expect(is.getSize()).to.be(0); - }); - - }); - - describe('intersectsRange', function() { - - it('returns false', function() { - expect(is.intersectsRange(0, 0)).to.be(false); - }); - - }); - - describe('isEmpty', function() { - - it('returns true', function() { - expect(is.isEmpty()).to.be(true); - }); - - }); - - describe('toString', function() { - - it('returns an empty string', function() { - expect(is.toString()).to.be.empty(); - }); - - }); - - }); - - describe('with a populated instance', function() { - - var is; - beforeEach(function() { - is = new ol.structs.IntegerSet([4, 6, 8, 10, 12, 14]); - }); - - describe('addRange', function() { - - it('inserts before the first element', function() { - is.addRange(0, 2); - expect(is.getArray()).to.eql([0, 2, 4, 6, 8, 10, 12, 14]); - }); - - it('extends the first element to the left', function() { - is.addRange(0, 4); - expect(is.getArray()).to.eql([0, 6, 8, 10, 12, 14]); - }); - - it('extends the first element to the right', function() { - is.addRange(6, 7); - expect(is.getArray()).to.eql([4, 7, 8, 10, 12, 14]); - }); - - it('merges the first two elements', function() { - is.addRange(6, 8); - expect(is.getArray()).to.eql([4, 10, 12, 14]); - }); - - it('extends middle elements to the left', function() { - is.addRange(7, 8); - expect(is.getArray()).to.eql([4, 6, 7, 10, 12, 14]); - }); - - it('extends middle elements to the right', function() { - is.addRange(10, 11); - expect(is.getArray()).to.eql([4, 6, 8, 11, 12, 14]); - }); - - it('merges the last two elements', function() { - is.addRange(10, 12); - expect(is.getArray()).to.eql([4, 6, 8, 14]); - }); - - it('extends the last element to the left', function() { - is.addRange(11, 12); - expect(is.getArray()).to.eql([4, 6, 8, 10, 11, 14]); - }); - - it('extends the last element to the right', function() { - is.addRange(14, 15); - expect(is.getArray()).to.eql([4, 6, 8, 10, 12, 15]); - }); - - it('inserts after the last element', function() { - is.addRange(16, 18); - expect(is.getArray()).to.eql([4, 6, 8, 10, 12, 14, 16, 18]); - }); - - }); - - describe('clear', function() { - - it('clears the instance', function() { - is.clear(); - expect(is.getArray()).to.be.empty(); - }); - - }); - - describe('findRange', function() { - - it('throws an exception when passed a negative size', function() { - expect(function() { - is.findRange(-1); - }).to.throwException(); - }); - - it('throws an exception when passed a zero size', function() { - expect(function() { - is.findRange(0); - }).to.throwException(); - }); - - it('finds the first range of size 1', function() { - expect(is.findRange(1)).to.be(4); - }); - - it('finds the first range of size 2', function() { - expect(is.findRange(2)).to.be(4); - }); - - it('returns -1 when no range can be found', function() { - expect(is.findRange(3)).to.be(-1); - }); - - }); - - describe('forEachRange', function() { - - it('calls the callback', function() { - var callback = sinon.spy(); - is.forEachRange(callback); - expect(callback).to.be.called(); - expect(callback.calledThrice).to.be(true); - expect(callback.args[0]).to.eql([4, 6]); - expect(callback.args[1]).to.eql([8, 10]); - expect(callback.args[2]).to.eql([12, 14]); - }); - - }); - - describe('forEachRangeInverted', function() { - - it('does call the callback', function() { - var callback = sinon.spy(); - is.forEachRangeInverted(0, 16, callback); - expect(callback.callCount).to.be(4); - expect(callback.args[0]).to.eql([0, 4]); - expect(callback.args[1]).to.eql([6, 8]); - expect(callback.args[2]).to.eql([10, 12]); - expect(callback.args[3]).to.eql([14, 16]); - }); - - }); - - - describe('getFirst', function() { - - it('returns the expected value', function() { - expect(is.getFirst()).to.be(4); - }); - - }); - - describe('getLast', function() { - - it('returns the expected value', function() { - expect(is.getLast()).to.be(14); - }); - - }); - - describe('getSize', function() { - - it('returns the expected value', function() { - expect(is.getSize()).to.be(6); - }); - - }); - - describe('intersectsRange', function() { - - it('returns the expected value for small ranges', function() { - expect(is.intersectsRange(1, 3)).to.be(false); - expect(is.intersectsRange(2, 4)).to.be(false); - expect(is.intersectsRange(3, 5)).to.be(true); - expect(is.intersectsRange(4, 6)).to.be(true); - expect(is.intersectsRange(5, 7)).to.be(true); - expect(is.intersectsRange(6, 8)).to.be(false); - expect(is.intersectsRange(7, 9)).to.be(true); - expect(is.intersectsRange(8, 10)).to.be(true); - expect(is.intersectsRange(9, 11)).to.be(true); - expect(is.intersectsRange(10, 12)).to.be(false); - expect(is.intersectsRange(11, 13)).to.be(true); - expect(is.intersectsRange(12, 14)).to.be(true); - expect(is.intersectsRange(13, 15)).to.be(true); - expect(is.intersectsRange(14, 16)).to.be(false); - expect(is.intersectsRange(15, 17)).to.be(false); - }); - - it('returns the expected value for large ranges', function() { - expect(is.intersectsRange(-3, 1)).to.be(false); - expect(is.intersectsRange(1, 5)).to.be(true); - expect(is.intersectsRange(1, 9)).to.be(true); - expect(is.intersectsRange(1, 13)).to.be(true); - expect(is.intersectsRange(1, 17)).to.be(true); - expect(is.intersectsRange(5, 9)).to.be(true); - expect(is.intersectsRange(5, 13)).to.be(true); - expect(is.intersectsRange(5, 17)).to.be(true); - expect(is.intersectsRange(9, 13)).to.be(true); - expect(is.intersectsRange(9, 17)).to.be(true); - expect(is.intersectsRange(13, 17)).to.be(true); - expect(is.intersectsRange(17, 21)).to.be(false); - }); - - }); - - describe('isEmpty', function() { - - it('returns false', function() { - expect(is.isEmpty()).to.be(false); - }); - - }); - - describe('removeRange', function() { - - it('removes the first part of the first element', function() { - is.removeRange(4, 5); - expect(is.getArray()).to.eql([5, 6, 8, 10, 12, 14]); - }); - - it('removes the last part of the first element', function() { - is.removeRange(5, 6); - expect(is.getArray()).to.eql([4, 5, 8, 10, 12, 14]); - }); - - it('removes the first element', function() { - is.removeRange(4, 6); - expect(is.getArray()).to.eql([8, 10, 12, 14]); - }); - - it('removes the first part of a middle element', function() { - is.removeRange(8, 9); - expect(is.getArray()).to.eql([4, 6, 9, 10, 12, 14]); - }); - - it('removes the last part of a middle element', function() { - is.removeRange(9, 10); - expect(is.getArray()).to.eql([4, 6, 8, 9, 12, 14]); - }); - - it('removes a middle element', function() { - is.removeRange(8, 10); - expect(is.getArray()).to.eql([4, 6, 12, 14]); - }); - - it('removes the first part of the last element', function() { - is.removeRange(12, 13); - expect(is.getArray()).to.eql([4, 6, 8, 10, 13, 14]); - }); - - it('removes the last part of the last element', function() { - is.removeRange(13, 14); - expect(is.getArray()).to.eql([4, 6, 8, 10, 12, 13]); - }); - - it('removes the last element', function() { - is.removeRange(12, 14); - expect(is.getArray()).to.eql([4, 6, 8, 10]); - }); - - it('can remove multiple ranges near the start', function() { - is.removeRange(3, 11); - expect(is.getArray()).to.eql([12, 14]); - }); - - it('can remove multiple ranges near the start', function() { - is.removeRange(7, 15); - expect(is.getArray()).to.eql([4, 6]); - }); - - it('throws an exception when passed an invalid range', function() { - expect(function() { - is.removeRange(2, 0); - }).to.throwException(); - }); - - }); - - describe('toString', function() { - - it('returns the expected value', function() { - expect(is.toString()).to.be('4-6, 8-10, 12-14'); - }); - }); - - }); - - describe('with fragmentation', function() { - - var is; - beforeEach(function() { - is = new ol.structs.IntegerSet([0, 1, 2, 4, 5, 8, 9, 12, 13, 15, 16, 17]); - }); - - describe('findRange', function() { - - it('finds the first range of size 1', function() { - expect(is.findRange(1)).to.be(0); - }); - - it('finds the first range of size 2', function() { - expect(is.findRange(2)).to.be(2); - }); - - it('finds the first range of size 3', function() { - expect(is.findRange(3)).to.be(5); - }); - - it('returns -1 when no range can be found', function() { - expect(is.findRange(4)).to.be(-1); - }); - - }); - - describe('getFirst', function() { - - it('returns the expected value', function() { - expect(is.getFirst()).to.be(0); - }); - - }); - - describe('getLast', function() { - - it('returns the expected value', function() { - expect(is.getLast()).to.be(17); - }); - - }); - - describe('getSize', function() { - - it('returns the expected value', function() { - expect(is.getSize()).to.be(12); - }); - - }); - - describe('removeRange', function() { - - it('removing an empty range has no effect', function() { - is.removeRange(0, 0); - expect(is.getArray()).to.eql( - [0, 1, 2, 4, 5, 8, 9, 12, 13, 15, 16, 17]); - }); - - it('can remove elements from the middle of range', function() { - is.removeRange(6, 7); - expect(is.getArray()).to.eql( - [0, 1, 2, 4, 5, 6, 7, 8, 9, 12, 13, 15, 16, 17]); - }); - - it('can remove multiple ranges', function() { - is.removeRange(2, 12); - expect(is.getArray()).to.eql([0, 1, 13, 15, 16, 17]); - }); - - it('can remove multiple ranges and reduce others', function() { - is.removeRange(0, 10); - expect(is.getArray()).to.eql([10, 12, 13, 15, 16, 17]); - }); - - it('can remove all ranges', function() { - is.removeRange(0, 18); - expect(is.getArray()).to.eql([]); - }); - - }); - - describe('toString', function() { - - it('returns the expected value', function() { - expect(is.toString()).to.be('0-1, 2-4, 5-8, 9-12, 13-15, 16-17'); - }); - - }); - - }); - - describe('compared to a slow reference implementation', function() { - - var SimpleIntegerSet = function() { - this.integers_ = {}; - }; - - SimpleIntegerSet.prototype.addRange = function(addStart, addStop) { - var i; - for (i = addStart; i < addStop; ++i) { - this.integers_[i.toString()] = true; - } - }; - - SimpleIntegerSet.prototype.clear = function() { - this.integers_ = {}; - }; - - SimpleIntegerSet.prototype.getArray = function() { - var integers = goog.array.map( - goog.object.getKeys(this.integers_), Number); - goog.array.sort(integers); - var arr = []; - var start = -1, stop; - var i; - for (i = 0; i < integers.length; ++i) { - if (start == -1) { - start = stop = integers[i]; - } else if (integers[i] == stop + 1) { - ++stop; - } else { - arr.push(start, stop + 1); - start = stop = integers[i]; - } - } - if (start != -1) { - arr.push(start, stop + 1); - } - return arr; - }; - - SimpleIntegerSet.prototype.removeRange = function(removeStart, removeStop) { - var i; - for (i = removeStart; i < removeStop; ++i) { - delete this.integers_[i.toString()]; - } - }; - - var is, sis; - beforeEach(function() { - is = new ol.structs.IntegerSet(); - sis = new SimpleIntegerSet(); - }); - - it('behaves identically with random adds', function() { - var addStart, addStop, i; - for (i = 0; i < 64; ++i) { - addStart = goog.math.randomInt(128); - addStop = addStart + goog.math.randomInt(16); - is.addRange(addStart, addStop); - sis.addRange(addStart, addStop); - expect(is.getArray()).to.eql(sis.getArray()); - } - }); - - it('behaves identically with random removes', function() { - is.addRange(0, 128); - sis.addRange(0, 128); - var i, removeStart, removeStop; - for (i = 0; i < 64; ++i) { - removeStart = goog.math.randomInt(128); - removeStop = removeStart + goog.math.randomInt(16); - is.removeRange(removeStart, removeStop); - sis.removeRange(removeStart, removeStop); - expect(is.getArray()).to.eql(sis.getArray()); - } - }); - - it('behaves identically with random adds and removes', function() { - var i, start, stop; - for (i = 0; i < 64; ++i) { - start = goog.math.randomInt(128); - stop = start + goog.math.randomInt(16); - if (Math.random() < 0.5) { - is.addRange(start, stop); - sis.addRange(start, stop); - } else { - is.removeRange(start, stop); - sis.removeRange(start, stop); - } - expect(is.getArray()).to.eql(sis.getArray()); - } - }); - - it('behaves identically with random adds, removes, and clears', function() { - var i, p, start, stop; - for (i = 0; i < 64; ++i) { - start = goog.math.randomInt(128); - stop = start + goog.math.randomInt(16); - p = Math.random(); - if (p < 0.45) { - is.addRange(start, stop); - sis.addRange(start, stop); - } else if (p < 0.9) { - is.removeRange(start, stop); - sis.removeRange(start, stop); - } else { - is.clear(); - sis.clear(); - } - expect(is.getArray()).to.eql(sis.getArray()); - } - }); - - }); - -}); - - -goog.require('goog.array'); -goog.require('goog.math'); -goog.require('goog.object'); -goog.require('ol.structs.IntegerSet');