diff --git a/build.py b/build.py index 82cdd86a3a..741389d301 100755 --- a/build.py +++ b/build.py @@ -324,13 +324,14 @@ def examples_star_json(name, match): '//jquery-1.7.js', '../externs/bingmaps.js', '../externs/bootstrap.js', + '../externs/closure-compiler.js', '../externs/example.js', '../externs/geojson.js', - '../externs/topojson.js', '../externs/oli.js', '../externs/proj4js.js', '../externs/tilejson.js', - '../externs/closure-compiler.js', + '../externs/topojson.js', + '../externs/vbarray.js', ], }) with open(t.name, 'w') as f: diff --git a/buildcfg/base.json b/buildcfg/base.json index 956f26a727..b11b1de0e3 100644 --- a/buildcfg/base.json +++ b/buildcfg/base.json @@ -54,7 +54,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js", ], "level": "VERBOSE", diff --git a/buildcfg/examples-all.json b/buildcfg/examples-all.json index ef7323f5b9..6fa2626238 100644 --- a/buildcfg/examples-all.json +++ b/buildcfg/examples-all.json @@ -10,7 +10,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js" ], "id": "simple", "inherits": "base.json", diff --git a/buildcfg/ol-all.json b/buildcfg/ol-all.json index 5e9c1057f4..dfee94cfc5 100644 --- a/buildcfg/ol-all.json +++ b/buildcfg/ol-all.json @@ -11,7 +11,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js" ], "inherits": "base.json", diff --git a/buildcfg/ol-simple.json b/buildcfg/ol-simple.json index 74b989a243..a2e3042793 100644 --- a/buildcfg/ol-simple.json +++ b/buildcfg/ol-simple.json @@ -21,7 +21,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js" ], "inherits": "ol.json", diff --git a/buildcfg/ol-whitespace.json b/buildcfg/ol-whitespace.json index fe8ffdf282..9c8ebe3bc5 100644 --- a/buildcfg/ol-whitespace.json +++ b/buildcfg/ol-whitespace.json @@ -21,7 +21,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js" ], "inherits": "ol.json", diff --git a/buildcfg/ol.json b/buildcfg/ol.json index 0b73e72219..d9db7932c4 100644 --- a/buildcfg/ol.json +++ b/buildcfg/ol.json @@ -21,7 +21,8 @@ "../externs/oli.js", "../externs/proj4js.js", "../externs/tilejson.js", - "../externs/topojson.js" + "../externs/topojson.js", + "../externs/vbarray.js" ], "inherits": "base.json", diff --git a/externs/vbarray.js b/externs/vbarray.js new file mode 100644 index 0000000000..1113b487f2 --- /dev/null +++ b/externs/vbarray.js @@ -0,0 +1,45 @@ +/** + * @externs + * @see http://msdn.microsoft.com/en-us/library/y39d47w8(v=vs.94).aspx + */ + + +/** + * FIXME check argument type + * @constructor + * @param {VBArray|string} safeArray + */ +var VBArray = function(safeArray) {}; + + +/** + * @return {number} + */ +VBArray.prototype.dimensions = function() {}; + + +/** + * @param {...number} var_args + * @return {*} + */ +VBArray.prototype.getItem = function(var_args) {}; + + +/** + * @param {number} dimension + * @return {*} + */ +VBArray.prototype.lbound = function(dimension) {}; + + +/** + * @return {Array.} + */ +VBArray.prototype.toArray = function() {}; + + +/** + * @param {number} dimension + * @return {*} + */ +VBArray.prototype.ubound = function(dimension) {}; diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index b8c3cf296b..5f30b01d63 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -839,6 +839,7 @@ /** * @typedef {Object} olx.source.VectorFileOptions + * @property {ArrayBuffer|undefined} arrayBuffer Array buffer. * @property {Array.|undefined} attributions Attributions. * @property {Document|undefined} doc Document. * @property {ol.Extent|undefined} extent Extent. diff --git a/src/ol/binary.js b/src/ol/binary.js new file mode 100644 index 0000000000..96f27492ee --- /dev/null +++ b/src/ol/binary.js @@ -0,0 +1,174 @@ +// FIXME Test on Internet Explorer with VBArray + +goog.provide('ol.binary.Buffer'); +goog.provide('ol.binary.IReader'); + +goog.require('goog.asserts'); +goog.require('goog.userAgent'); +goog.require('ol.BrowserFeature'); + + + +/** + * @constructor + * @param {ArrayBuffer|string} data Data. + */ +ol.binary.Buffer = function(data) { + + /** + * @private + * @type {ArrayBuffer|string} + */ + this.data_ = data; + +}; + + +/** + * @return {ol.binary.IReader} Reader. + */ +ol.binary.Buffer.prototype.getReader = function() { + var data = this.data_; + if (ol.BrowserFeature.HAS_ARRAY_BUFFER) { + var arrayBuffer; + if (data instanceof ArrayBuffer) { + arrayBuffer = data; + } else if (goog.isString(data)) { + // FIXME check what happens with Unicode + arrayBuffer = new ArrayBuffer(data.length); + var uint8View = new Uint8Array(arrayBuffer); + var i, ii; + for (i = 0, ii = data.length; i < ii; ++i) { + uint8View[i] = data.charCodeAt(i); + } + } else { + goog.asserts.fail(); + return null; + } + return new ol.binary.ArrayBufferReader(arrayBuffer); + } else { + goog.asserts.assert(goog.isString(data)); + goog.asserts.assert( + goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10.0')); + return new ol.binary.ArrayReader(new VBArray(data).toArray()); + } +}; + + + +/** + * @interface + */ +ol.binary.IReader = function() {}; + + +/** + * @return {boolean} At EOF. + */ +ol.binary.IReader.prototype.atEOF = function() {}; + + +/** + * @return {number} Byte. + */ +ol.binary.IReader.prototype.readByte = function() {}; + + + +/** + * @constructor + * @param {ArrayBuffer} arrayBuffer Array buffer. + * @implements {ol.binary.IReader} + */ +ol.binary.ArrayBufferReader = function(arrayBuffer) { + + /** + * @private + * @type {Uint8Array} + */ + this.uint8View_ = new Uint8Array(arrayBuffer); + + /** + * @private + * @type {number} + */ + this.length_ = this.uint8View_.length; + + /** + * @private + * @type {number} + */ + this.offset_ = 0; + +}; + + +/** + * @inheritDoc + */ +ol.binary.ArrayBufferReader.prototype.atEOF = function() { + return this.offset_ == this.length_; +}; + + +/** + * @inheritDoc + */ +ol.binary.ArrayBufferReader.prototype.readByte = function() { + if (this.offset_ < this.length_) { + return this.uint8View_[this.offset_++]; + } else { + goog.asserts.fail(); + return 0; + } +}; + + + +/** + * @constructor + * @implements {ol.binary.IReader} + * @param {Array.} array Array. + */ +ol.binary.ArrayReader = function(array) { + + /** + * @private + * @type {Array.} + */ + this.array_ = array; + + /** + * @private + * @type {number} + */ + this.length_ = array.length; + + /** + * @private + * @type {number} + */ + this.offset_ = 0; + +}; + + +/** + * @inheritDoc + */ +ol.binary.ArrayReader.prototype.atEOF = function() { + return this.offset_ == this.length_; +}; + + +/** + * @inheritDoc + */ +ol.binary.ArrayReader.prototype.readByte = function() { + if (this.offset_ < this.length_) { + return this.array_[this.offset_++]; + } else { + goog.asserts.fail(); + return 0; + } +}; diff --git a/src/ol/browserfeature.js b/src/ol/browserfeature.js index 1695160557..265ba06fdd 100644 --- a/src/ol/browserfeature.js +++ b/src/ol/browserfeature.js @@ -73,6 +73,14 @@ ol.IS_LEGACY_IE = goog.userAgent.IE && ol.BrowserFeature.DEVICE_PIXEL_RATIO = goog.global.devicePixelRatio || 1; +/** + * True if the browser supports ArrayBuffers. + * @type {boolean} + * @todo stability experimental + */ +ol.BrowserFeature.HAS_ARRAY_BUFFER = 'ArrayBuffer' in goog.global; + + /** * True if the browser's Canvas implementation implements {get,set}LineDash. * @type {boolean} diff --git a/src/ol/format/binaryformat.js b/src/ol/format/binaryformat.js new file mode 100644 index 0000000000..5cf01cfdd9 --- /dev/null +++ b/src/ol/format/binaryformat.js @@ -0,0 +1,107 @@ +goog.provide('ol.format.Binary'); + +goog.require('goog.asserts'); +goog.require('ol.BrowserFeature'); +goog.require('ol.binary.Buffer'); +goog.require('ol.format.Format'); +goog.require('ol.format.FormatType'); +goog.require('ol.proj'); + + + +/** + * @constructor + * @extends {ol.format.Format} + */ +ol.format.Binary = function() { + goog.base(this); +}; +goog.inherits(ol.format.Binary, ol.format.Format); + + +/** + * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @private + * @return {ol.binary.Buffer} Buffer. + */ +ol.format.Binary.getBuffer_ = function(source) { + if (ol.BrowserFeature.HAS_ARRAY_BUFFER && source instanceof ArrayBuffer) { + return new ol.binary.Buffer(source); + } else if (goog.isString(source)) { + return new ol.binary.Buffer(source); + } else { + goog.asserts.fail(); + return null; + } +}; + + +/** + * @inheritDoc + */ +ol.format.Binary.prototype.getType = function() { + return ol.format.FormatType.BINARY; +}; + + +/** + * @inheritDoc + */ +ol.format.Binary.prototype.readFeature = function(source) { + return this.readFeatureFromBuffer(ol.format.Binary.getBuffer_(source)); +}; + + +/** + * @inheritDoc + */ +ol.format.Binary.prototype.readFeatures = function(source) { + return this.readFeaturesFromBuffer(ol.format.Binary.getBuffer_(source)); +}; + + +/** + * @param {ol.binary.Buffer} buffer Buffer. + * @protected + * @return {ol.Feature} Feature. + */ +ol.format.Binary.prototype.readFeatureFromBuffer = goog.abstractMethod; + + +/** + * @param {ol.binary.Buffer} buffer Buffer. + * @protected + * @return {Array.} Feature. + */ +ol.format.Binary.prototype.readFeaturesFromBuffer = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.format.Binary.prototype.readGeometry = function(source) { + return this.readGeometryFromBuffer(ol.format.Binary.getBuffer_(source)); +}; + + +/** + * @param {ol.binary.Buffer} buffer Buffer. + * @protected + * @return {ol.geom.Geometry} Geometry. + */ +ol.format.Binary.prototype.readGeometryFromBuffer = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.format.Binary.prototype.readProjection = function(source) { + return this.readProjectionFromBuffer(ol.format.Binary.getBuffer_(source)); +}; + + +/** + * @param {ol.binary.Buffer} buffer Buffer. + * @return {ol.proj.Projection} Projection. + */ +ol.format.Binary.prototype.readProjectionFromBuffer = goog.abstractMethod; diff --git a/src/ol/format/format.js b/src/ol/format/format.js index 022689936b..69cf3ed97b 100644 --- a/src/ol/format/format.js +++ b/src/ol/format/format.js @@ -36,28 +36,28 @@ ol.format.Format.prototype.getType = goog.abstractMethod; /** - * @param {Document|Node|Object|string} source Source. + * @param {ArrayBuffer|Document|Node|Object|string} source Source. * @return {ol.Feature} Feature. */ ol.format.Format.prototype.readFeature = goog.abstractMethod; /** - * @param {Document|Node|Object|string} source Source. + * @param {ArrayBuffer|Document|Node|Object|string} source Source. * @return {Array.} Features. */ ol.format.Format.prototype.readFeatures = goog.abstractMethod; /** - * @param {Document|Node|Object|string} source Source. + * @param {ArrayBuffer|Document|Node|Object|string} source Source. * @return {ol.geom.Geometry} Geometry. */ ol.format.Format.prototype.readGeometry = goog.abstractMethod; /** - * @param {Document|Node|Object|string} source Source. + * @param {ArrayBuffer|Document|Node|Object|string} source Source. * @return {ol.proj.Projection} Projection. */ ol.format.Format.prototype.readProjection = goog.abstractMethod; @@ -65,20 +65,20 @@ ol.format.Format.prototype.readProjection = goog.abstractMethod; /** * @param {ol.Feature} feature Feature. - * @return {Node|Object|string} Result. + * @return {ArrayBuffer|Node|Object|string} Result. */ ol.format.Format.prototype.writeFeature = goog.abstractMethod; /** * @param {Array.} features Features. - * @return {Node|Object|string} Result. + * @return {ArrayBuffer|Node|Object|string} Result. */ ol.format.Format.prototype.writeFeatures = goog.abstractMethod; /** * @param {ol.geom.Geometry} geometry Geometry. - * @return {Node|Object|string} Node. + * @return {ArrayBuffer|Node|Object|string} Node. */ ol.format.Format.prototype.writeGeometry = goog.abstractMethod; diff --git a/src/ol/source/vectorfilesource.js b/src/ol/source/vectorfilesource.js index c2fd85339a..11ef6a65f7 100644 --- a/src/ol/source/vectorfilesource.js +++ b/src/ol/source/vectorfilesource.js @@ -4,8 +4,13 @@ goog.provide('ol.source.VectorFile'); goog.require('goog.asserts'); +goog.require('goog.dispose'); +goog.require('goog.events'); +goog.require('goog.net.EventType'); goog.require('goog.net.XhrIo'); +goog.require('goog.net.XhrIo.ResponseType'); goog.require('goog.userAgent'); +goog.require('ol.BrowserFeature'); goog.require('ol.format.FormatType'); goog.require('ol.proj'); goog.require('ol.source.State'); @@ -53,17 +58,38 @@ ol.source.VectorFile = function(opt_options) { this.readFeatures_(options.text); } + if (goog.isDef(options.arrayBuffer)) { + this.readFeatures_(options.arrayBuffer); + } + if (goog.isDef(options.url) || goog.isDef(options.urls)) { this.setState(ol.source.State.LOADING); - var handleXhrIo = goog.bind(this.handleXhrIo_, this); + + var type = this.format.getType(); + var responseType; + if (type == ol.format.FormatType.BINARY && + ol.BrowserFeature.HAS_ARRAY_BUFFER) { + responseType = goog.net.XhrIo.ResponseType.ARRAY_BUFFER; + } else { + responseType = goog.net.XhrIo.ResponseType.TEXT; + } + var xhrIo; if (goog.isDef(options.url)) { - goog.net.XhrIo.send(options.url, handleXhrIo); + xhrIo = new goog.net.XhrIo(); + xhrIo.setResponseType(responseType); + goog.events.listen(xhrIo, goog.net.EventType.COMPLETE, + goog.bind(this.handleXhrIo_, this)); + xhrIo.send(options.url); } if (goog.isDef(options.urls)) { var urls = options.urls; var i, ii; for (i = 0, ii = urls.length; i < ii; ++i) { - goog.net.XhrIo.send(urls[i], handleXhrIo); + xhrIo = new goog.net.XhrIo(); + xhrIo.setResponseType(responseType); + goog.events.listen(xhrIo, goog.net.EventType.COMPLETE, + goog.bind(this.handleXhrIo_, this)); + xhrIo.send(urls[i]); } } } @@ -77,13 +103,16 @@ goog.inherits(ol.source.VectorFile, ol.source.Vector); * @private */ ol.source.VectorFile.prototype.handleXhrIo_ = function(event) { - var xhrIo = /** @type {goog.net.XhrIo} */ (event.target); + var xhrIo = event.target; + goog.asserts.assertInstanceof(xhrIo, goog.net.XhrIo); if (xhrIo.isSuccess()) { var type = this.format.getType(); - /** @type {Document|Node|Object|string|undefined} */ + /** @type {ArrayBuffer|Document|Node|Object|string|undefined} */ var source; - if (type == ol.format.FormatType.BINARY) { - // FIXME + if (type == ol.format.FormatType.BINARY && + ol.BrowserFeature.HAS_ARRAY_BUFFER) { + source = xhrIo.getResponse(); + goog.asserts.assertInstanceof(source, ArrayBuffer); } else if (type == ol.format.FormatType.JSON) { source = xhrIo.getResponseJson(); } else if (type == ol.format.FormatType.TEXT) { @@ -98,6 +127,7 @@ ol.source.VectorFile.prototype.handleXhrIo_ = function(event) { } else { goog.asserts.fail(); } + goog.dispose(xhrIo); if (goog.isDef(source)) { this.readFeatures_(source); } else { @@ -111,7 +141,7 @@ ol.source.VectorFile.prototype.handleXhrIo_ = function(event) { /** - * @param {Document|Node|Object|string} source Source. + * @param {ArrayBuffer|Document|Node|Object|string} source Source. * @private */ ol.source.VectorFile.prototype.readFeatures_ = function(source) {