Remove unused WebGL related code
This commit is contained in:
@@ -1,10 +1,8 @@
|
|||||||
goog.provide('ol.structs.Buffer');
|
goog.provide('ol.structs.Buffer');
|
||||||
|
|
||||||
goog.require('goog.array');
|
goog.require('goog.array');
|
||||||
goog.require('goog.asserts');
|
|
||||||
goog.require('goog.webgl');
|
goog.require('goog.webgl');
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.structs.IntegerSet');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,11 +19,10 @@ ol.structs.BufferUsage = {
|
|||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Array.<number>=} opt_arr Array.
|
* @param {Array.<number>=} opt_arr Array.
|
||||||
* @param {number=} opt_used Used.
|
|
||||||
* @param {number=} opt_usage Usage.
|
* @param {number=} opt_usage Usage.
|
||||||
* @struct
|
* @struct
|
||||||
*/
|
*/
|
||||||
ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) {
|
ol.structs.Buffer = function(opt_arr, opt_usage) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -33,43 +30,6 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) {
|
|||||||
*/
|
*/
|
||||||
this.arr_ = goog.isDef(opt_arr) ? opt_arr : [];
|
this.arr_ = goog.isDef(opt_arr) ? opt_arr : [];
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Array.<ol.structs.IntegerSet>}
|
|
||||||
*/
|
|
||||||
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
|
* @private
|
||||||
* @type {number}
|
* @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.<number>} 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.<number>} Array.
|
* @return {Array.<number>} 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.
|
* @return {number} Usage.
|
||||||
*/
|
*/
|
||||||
ol.structs.Buffer.prototype.getUsage = function() {
|
ol.structs.Buffer.prototype.getUsage = function() {
|
||||||
return this.usage_;
|
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.<number>} 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);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -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.<number>=} opt_arr Array.
|
|
||||||
*/
|
|
||||||
ol.structs.IntegerSet = function(opt_arr) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Array.<number>}
|
|
||||||
*/
|
|
||||||
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.<number>} 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.<number>} 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(', ');
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -7,14 +7,12 @@ goog.require('goog.log');
|
|||||||
goog.require('goog.object');
|
goog.require('goog.object');
|
||||||
goog.require('ol.has');
|
goog.require('ol.has');
|
||||||
goog.require('ol.structs.Buffer');
|
goog.require('ol.structs.Buffer');
|
||||||
goog.require('ol.structs.IntegerSet');
|
|
||||||
goog.require('ol.webgl.WebGLContextEventType');
|
goog.require('ol.webgl.WebGLContextEventType');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{buf: ol.structs.Buffer,
|
* @typedef {{buf: ol.structs.Buffer,
|
||||||
* buffer: WebGLBuffer,
|
* buffer: WebGLBuffer}}
|
||||||
* dirtySet: ol.structs.IntegerSet}}
|
|
||||||
*/
|
*/
|
||||||
ol.webgl.BufferCacheEntry;
|
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 {number} target Target.
|
||||||
* @param {ol.structs.Buffer} buf Buffer.
|
* @param {ol.structs.Buffer} buf Buffer.
|
||||||
*/
|
*/
|
||||||
@@ -99,17 +100,6 @@ ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
|
|||||||
if (bufferKey in this.bufferCache_) {
|
if (bufferKey in this.bufferCache_) {
|
||||||
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
||||||
gl.bindBuffer(target, bufferCacheEntry.buffer);
|
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 {
|
} else {
|
||||||
var buffer = gl.createBuffer();
|
var buffer = gl.createBuffer();
|
||||||
gl.bindBuffer(target, buffer);
|
gl.bindBuffer(target, buffer);
|
||||||
@@ -118,12 +108,9 @@ ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
|
|||||||
target == goog.webgl.ARRAY_BUFFER ?
|
target == goog.webgl.ARRAY_BUFFER ?
|
||||||
new Float32Array(arr) : new Uint16Array(arr),
|
new Float32Array(arr) : new Uint16Array(arr),
|
||||||
buf.getUsage());
|
buf.getUsage());
|
||||||
var dirtySet = new ol.structs.IntegerSet();
|
|
||||||
buf.addDirtySet(dirtySet);
|
|
||||||
this.bufferCache_[bufferKey] = {
|
this.bufferCache_[bufferKey] = {
|
||||||
buf: buf,
|
buf: buf,
|
||||||
buffer: buffer,
|
buffer: buffer
|
||||||
dirtySet: dirtySet
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -137,7 +124,6 @@ ol.webgl.Context.prototype.deleteBuffer = function(buf) {
|
|||||||
var bufferKey = goog.getUid(buf);
|
var bufferKey = goog.getUid(buf);
|
||||||
goog.asserts.assert(bufferKey in this.bufferCache_);
|
goog.asserts.assert(bufferKey in this.bufferCache_);
|
||||||
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
var bufferCacheEntry = this.bufferCache_[bufferKey];
|
||||||
bufferCacheEntry.buf.removeDirtySet(bufferCacheEntry.dirtySet);
|
|
||||||
if (!gl.isContextLost()) {
|
if (!gl.isContextLost()) {
|
||||||
gl.deleteBuffer(bufferCacheEntry.buffer);
|
gl.deleteBuffer(bufferCacheEntry.buffer);
|
||||||
}
|
}
|
||||||
@@ -149,9 +135,6 @@ ol.webgl.Context.prototype.deleteBuffer = function(buf) {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
ol.webgl.Context.prototype.disposeInternal = function() {
|
ol.webgl.Context.prototype.disposeInternal = function() {
|
||||||
goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) {
|
|
||||||
bufferCacheEntry.buf.removeDirtySet(bufferCacheEntry.dirtySet);
|
|
||||||
});
|
|
||||||
var gl = this.getGL();
|
var gl = this.getGL();
|
||||||
if (!gl.isContextLost()) {
|
if (!gl.isContextLost()) {
|
||||||
goog.object.forEach(this.bufferCache_, function(bufferCacheEntry) {
|
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.
|
* @param {ol.webgl.Shader} shaderObject Shader object.
|
||||||
* @return {WebGLShader} Shader.
|
* @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.Fragment} fragmentShaderObject Fragment shader.
|
||||||
* @param {ol.webgl.shader.Vertex} vertexShaderObject Vertex shader.
|
* @param {ol.webgl.shader.Vertex} vertexShaderObject Vertex shader.
|
||||||
* @return {WebGLProgram} Program.
|
* @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.
|
* @param {WebGLProgram} program Program.
|
||||||
* @return {boolean} Changed.
|
* @return {boolean} Changed.
|
||||||
* @api
|
* @api
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ describe('ol.structs.Buffer', function() {
|
|||||||
|
|
||||||
it('constructs an empty instance', function() {
|
it('constructs an empty instance', function() {
|
||||||
expect(b.getArray()).to.be.empty();
|
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();
|
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() {
|
describe('getArray', function() {
|
||||||
|
|
||||||
it('returns an empty array', 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.Buffer');
|
||||||
goog.require('ol.structs.IntegerSet');
|
|
||||||
|
|||||||
@@ -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');
|
|
||||||
Reference in New Issue
Block a user