├── .tm_properties ├── .gitignore ├── examples ├── mapserv.ico ├── mapserv.html ├── mapserv.js └── cache.js ├── tests ├── data │ ├── gmap │ │ ├── data │ │ │ ├── bath_mapserver.tfw │ │ │ ├── grid.dbf │ │ │ ├── grid.shp │ │ │ ├── grid.shx │ │ │ ├── park.dbf │ │ │ ├── park.shp │ │ │ ├── park.shx │ │ │ ├── rail.dbf │ │ │ ├── rail.shp │ │ │ ├── rail.shx │ │ │ ├── road.dbf │ │ │ ├── road.shp │ │ │ ├── road.shx │ │ │ ├── land_fn.dbf │ │ │ ├── land_fn.shp │ │ │ ├── land_fn.shx │ │ │ ├── drain_fn.dbf │ │ │ ├── drain_fn.shp │ │ │ ├── drain_fn.shx │ │ │ ├── drainage.dbf │ │ │ ├── drainage.shp │ │ │ ├── drainage.shx │ │ │ ├── fedlimit.shp │ │ │ ├── fedlimit.shx │ │ │ ├── popplace.dbf │ │ │ ├── popplace.shp │ │ │ ├── popplace.shx │ │ │ ├── province.dbf │ │ │ ├── province.shp │ │ │ ├── province.shx │ │ │ ├── bath_mapserver.tif │ │ │ └── fedlimit.dbf │ │ ├── etc │ │ │ ├── Vera.ttf │ │ │ ├── VeraBI.ttf │ │ │ ├── VeraBd.ttf │ │ │ ├── VeraIt.ttf │ │ │ ├── VeraMoBI.ttf │ │ │ ├── VeraMoBd.ttf │ │ │ ├── VeraMoIt.ttf │ │ │ ├── VeraMono.ttf │ │ │ ├── VeraSe.ttf │ │ │ ├── VeraSeBd.ttf │ │ │ ├── fonts.txt │ │ │ ├── symbols.sym │ │ │ ├── symbols.txt │ │ │ └── COPYRIGHT.TXT │ │ └── htdocs │ │ │ ├── gmap75_key.map │ │ │ ├── gmap75_wfs.map │ │ │ ├── gmap75.map │ │ │ ├── gmap75_wms.map │ │ │ └── gmap75_platform.map │ ├── province.dbf │ ├── province.shp │ ├── province.shx │ ├── wgs_province.dbf │ ├── wgs_province.shp │ ├── wgs_province.shx │ ├── test_buffer_60201.png │ ├── test_buffer_60401.png │ ├── test_buffer_60500.png │ ├── wgs_province.prj │ ├── symbolset.txt │ └── test.map ├── tests.js └── tests copy.js ├── .gitmodules ├── binding.gyp ├── src ├── ms_layers.hpp ├── ms_rect.hpp ├── ms_hashtable.hpp ├── ms_outputformat.hpp ├── ms_projection.hpp ├── ms_point.hpp ├── ms_error.hpp ├── ms_layer.hpp ├── utils.hpp ├── ms_map.hpp ├── mapserver.hpp ├── ms_hashtable.cpp ├── ms_layers.cpp ├── ms_error.cpp ├── ms_projection.cpp ├── ms_outputformat.cpp ├── ms_point.cpp ├── ms_rect.cpp ├── ms_layer.cpp ├── mapserver.cpp └── ms_map.cpp ├── LICENSE.md ├── package.json ├── mapserver.js ├── .travis.yml ├── tools ├── install-deps.sh └── config.py └── README.md /.tm_properties: -------------------------------------------------------------------------------- 1 | include="{$include,.travis.yml}" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | node_modules/* 3 | .DS_Store 4 | test_out* 5 | -------------------------------------------------------------------------------- /examples/mapserv.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/examples/mapserv.ico -------------------------------------------------------------------------------- /tests/data/gmap/data/bath_mapserver.tfw: -------------------------------------------------------------------------------- 1 | 1979.5 2 | 0.0 3 | 0.0 4 | -1979.5 5 | -2750560 6 | 4673130 7 | -------------------------------------------------------------------------------- /tests/data/province.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/province.dbf -------------------------------------------------------------------------------- /tests/data/province.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/province.shp -------------------------------------------------------------------------------- /tests/data/province.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/province.shx -------------------------------------------------------------------------------- /tests/data/wgs_province.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/wgs_province.dbf -------------------------------------------------------------------------------- /tests/data/wgs_province.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/wgs_province.shp -------------------------------------------------------------------------------- /tests/data/wgs_province.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/wgs_province.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/grid.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/grid.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/grid.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/grid.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/grid.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/grid.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/park.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/park.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/park.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/park.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/park.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/park.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/rail.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/rail.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/rail.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/rail.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/rail.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/rail.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/road.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/road.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/road.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/road.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/road.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/road.shx -------------------------------------------------------------------------------- /tests/data/gmap/etc/Vera.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/Vera.ttf -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/hashlib"] 2 | path = deps/hashlib 3 | url = https://github.com/brainfucker/hashlib.git 4 | -------------------------------------------------------------------------------- /tests/data/gmap/data/land_fn.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/land_fn.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/land_fn.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/land_fn.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/land_fn.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/land_fn.shx -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraBI.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraBd.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraIt.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraMoBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraMoBI.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraMoBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraMoBd.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraMoIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraMoIt.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraMono.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraSe.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraSe.ttf -------------------------------------------------------------------------------- /tests/data/gmap/etc/VeraSeBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/etc/VeraSeBd.ttf -------------------------------------------------------------------------------- /tests/data/test_buffer_60201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/test_buffer_60201.png -------------------------------------------------------------------------------- /tests/data/test_buffer_60401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/test_buffer_60401.png -------------------------------------------------------------------------------- /tests/data/test_buffer_60500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/test_buffer_60500.png -------------------------------------------------------------------------------- /tests/data/gmap/data/drain_fn.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drain_fn.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/drain_fn.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drain_fn.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/drain_fn.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drain_fn.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/drainage.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drainage.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/drainage.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drainage.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/drainage.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/drainage.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/fedlimit.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/fedlimit.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/fedlimit.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/fedlimit.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/popplace.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/popplace.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/popplace.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/popplace.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/popplace.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/popplace.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/province.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/province.dbf -------------------------------------------------------------------------------- /tests/data/gmap/data/province.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/province.shp -------------------------------------------------------------------------------- /tests/data/gmap/data/province.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/province.shx -------------------------------------------------------------------------------- /tests/data/gmap/data/bath_mapserver.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagameba/node-mapserver/HEAD/tests/data/gmap/data/bath_mapserver.tif -------------------------------------------------------------------------------- /tests/data/wgs_province.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /tests/data/symbolset.txt: -------------------------------------------------------------------------------- 1 | symbolset 2 | 3 | symbol 4 | name "arrow" 5 | type vector 6 | points 7 | 0 1 8 | 3 1 9 | -99 -99 10 | 2 0 11 | 3 1 12 | 2 2 13 | end 14 | end 15 | 16 | end 17 | -------------------------------------------------------------------------------- /tests/data/gmap/etc/fonts.txt: -------------------------------------------------------------------------------- 1 | sans Vera.ttf 2 | sans-bold VeraBd.ttf 3 | sans-italic VeraIt.ttf 4 | sans-bold-italic VeraBi.ttf 5 | serif VeraSe.ttf 6 | serif-bold VeraSeBd.ttf 7 | mono VeraMono.ttf 8 | mono-bold VeraMoBd.ttf 9 | mono-italic VeraMoIt.ttf 10 | mono-bold-italic VeraMoBi.ttf 11 | 12 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "mapserver", 5 | "sources": [ 6 | "src/mapserver.cpp", 7 | "src/ms_error.cpp", 8 | "src/ms_layer.cpp", 9 | "src/ms_layers.cpp", 10 | "src/ms_map.cpp", 11 | "src/ms_outputformat.cpp", 12 | "src/ms_point.cpp", 13 | "src/ms_projection.cpp", 14 | "src/ms_hashtable.cpp", 15 | "src/ms_rect.cpp" 16 | ], 17 | "libraries":["-lmapserver"], 18 | "include_dirs": [ 19 | " 5 | #include 6 | #include "utils.hpp" 7 | 8 | class MSLayers: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | static void Initialize(v8::Local target); 12 | static NAN_METHOD(New); 13 | static v8::Local NewInstance(mapObj *map); 14 | 15 | static NAN_INDEX_GETTER(IndexGetter); 16 | static NAN_PROPERTY_GETTER(NamedGetter); 17 | 18 | MSLayers(); 19 | MSLayers(mapObj *map); 20 | inline mapObj *get() { return this_; } 21 | mapObj *this_; 22 | 23 | private: 24 | ~MSLayers(); 25 | 26 | }; 27 | #endif 28 | -------------------------------------------------------------------------------- /src/ms_rect.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_RECT_H 2 | #define _NODE_MS_RECT_H 3 | 4 | #include 5 | #include 6 | #include "ms_projection.hpp" 7 | 8 | class MSRect: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | static void Initialize(v8::Local target); 12 | static NAN_METHOD(New); 13 | static v8::Local NewInstance(rectObj *rect); 14 | 15 | static NAN_GETTER(PropertyGetter); 16 | static NAN_SETTER(PropertySetter); 17 | 18 | static NAN_METHOD(Project); 19 | 20 | MSRect(); 21 | MSRect(rectObj *rect); 22 | inline rectObj *get() { return this_; }; 23 | rectObj *this_; 24 | bool owner; 25 | 26 | private: 27 | ~MSRect(); 28 | 29 | }; 30 | #endif 31 | -------------------------------------------------------------------------------- /src/ms_hashtable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_HASHTABLE_H 2 | #define _NODE_MS_HASHTABLE_H 3 | 4 | #include 5 | #include 6 | #include "utils.hpp" 7 | 8 | class MSHashTable: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | static void Initialize(v8::Local target); 12 | static NAN_METHOD(New); 13 | static v8::Local NewInstance(hashTableObj *table); 14 | 15 | static NAN_PROPERTY_GETTER(NamedPropertyGetter); 16 | static NAN_PROPERTY_SETTER(NamedPropertySetter); 17 | 18 | MSHashTable(); 19 | MSHashTable(hashTableObj *table); 20 | inline hashTableObj *get() { return this_; } 21 | hashTableObj *this_; 22 | 23 | private: 24 | ~MSHashTable(); 25 | 26 | }; 27 | #endif 28 | -------------------------------------------------------------------------------- /src/ms_outputformat.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_OUTPUTFORMAT_H 2 | #define _NODE_MS_OUTPUTFORMAT_H 3 | 4 | #include 5 | #include 6 | #include "utils.hpp" 7 | 8 | class MSOutputFormat: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | static void Initialize(v8::Local target); 12 | static NAN_METHOD(New); 13 | static v8::Local NewInstance(outputFormatObj *of); 14 | 15 | static NAN_GETTER(PropertyGetter); 16 | static NAN_SETTER(PropertySetter); 17 | 18 | MSOutputFormat(); 19 | MSOutputFormat(outputFormatObj *of); 20 | inline outputFormatObj *get() { return this_; } 21 | outputFormatObj *this_; 22 | 23 | private: 24 | ~MSOutputFormat(); 25 | 26 | }; 27 | #endif 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Paul Spencer 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /src/ms_projection.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_PROJECTION_H 2 | #define _NODE_MS_PROJECTION_H 3 | 4 | #include 5 | #include 6 | #include "utils.hpp" 7 | 8 | class MSProjection: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | static void Initialize(v8::Local target); 12 | static NAN_METHOD(New); 13 | static v8::Local NewInstance(projectionObj *proj); 14 | 15 | static NAN_GETTER(Units); 16 | static NAN_GETTER(ProjString); 17 | static NAN_SETTER(SetProjString); 18 | 19 | MSProjection(); 20 | MSProjection(projectionObj *proj); 21 | inline projectionObj *get() { return this_; } 22 | projectionObj *this_; 23 | bool owner; 24 | 25 | private: 26 | ~MSProjection(); 27 | 28 | }; 29 | #endif 30 | -------------------------------------------------------------------------------- /src/ms_point.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_POINT_H 2 | #define _NODE_MS_POINT_H 3 | 4 | #include 5 | #include 6 | #include "ms_projection.hpp" 7 | #include "utils.hpp" 8 | 9 | class MSPoint: public Nan::ObjectWrap { 10 | public: 11 | static Nan::Persistent constructor; 12 | static void Initialize(v8::Local target); 13 | static NAN_METHOD(New); 14 | static v8::Local NewInstance(pointObj *point); 15 | 16 | static NAN_GETTER(PropertyGetter); 17 | static NAN_SETTER(PropertySetter); 18 | 19 | static NAN_METHOD(Project); 20 | static NAN_METHOD(DistanceToPoint); 21 | 22 | MSPoint(); 23 | MSPoint(pointObj *point); 24 | inline pointObj *get() { return this_; } 25 | bool owner; 26 | 27 | private: 28 | ~MSPoint(); 29 | pointObj *this_; 30 | 31 | }; 32 | #endif 33 | -------------------------------------------------------------------------------- /src/ms_error.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __NODE_MS_ERROR_H__ 2 | #define __NODE_MS_ERROR_H__ 3 | 4 | #include 5 | #include 6 | #include "utils.hpp" 7 | 8 | class MSError: public Nan::ObjectWrap { 9 | public: 10 | static Nan::Persistent constructor; 11 | 12 | static void Initialize(v8::Local target); 13 | static NAN_METHOD(New); 14 | static v8::Local NewInstance(errorObj* err_ptr); 15 | 16 | MSError(); 17 | MSError(errorObj *err); 18 | inline errorObj *get() { return this_; } 19 | 20 | protected: 21 | static NAN_PROPERTY_GETTER(NamedPropertyGetter); 22 | static NAN_PROPERTY_QUERY(NamedPropertyQuery); 23 | static NAN_PROPERTY_ENUMERATOR(NamedPropertyEnumerator); 24 | 25 | private: 26 | ~MSError(); 27 | errorObj *this_; 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-mapserver", 3 | "version": "0.0.1", 4 | "description": "node bindings for libmapserver", 5 | "main": "mapserver.js", 6 | "directories": { 7 | "example": "examples", 8 | "test": "tests" 9 | }, 10 | "config": { 11 | "include_dir": "", 12 | "lib_dir": "" 13 | }, 14 | "scripts": { 15 | "test": "node_modules/.bin/mocha -R spec tests/tests.js", 16 | "install": "node-gyp configure build" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/pagameba/node-mapserver.git" 21 | }, 22 | "keywords": [ 23 | "mapserver" 24 | ], 25 | "author": "Paul Spencer", 26 | "license": "MIT", 27 | "gypfile": true, 28 | "readmeFilename": "README.md", 29 | "gitHead": "32f694866ad22c3a033c4d907f20e4802bf728c5", 30 | "devDependencies": { 31 | "mocha": "^1.10.0", 32 | "nan": "^2.3.3" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ms_layer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_LAYER_H 2 | #define _NODE_MS_LAYER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "ms_hashtable.hpp" 8 | #include "utils.hpp" 9 | 10 | class MSLayer: public Nan::ObjectWrap { 11 | public: 12 | static Nan::Persistent constructor; 13 | static void Initialize(v8::Local target); 14 | static NAN_METHOD(New); 15 | static v8::Local NewInstance(layerObj* ptr); 16 | 17 | static NAN_GETTER(PropertyGetter); 18 | static NAN_SETTER(PropertySetter); 19 | 20 | static NAN_METHOD(GetGridIntersectionCoordinates); 21 | static NAN_METHOD(UpdateFromString); 22 | #if MS_VERSION_NUM >= 60400 23 | static NAN_METHOD(ToString); 24 | #endif 25 | 26 | MSLayer(); 27 | MSLayer(layerObj *layer); 28 | inline layerObj *get() { return this_; } 29 | layerObj *this_; 30 | 31 | private: 32 | ~MSLayer(); 33 | 34 | }; 35 | #endif 36 | -------------------------------------------------------------------------------- /mapserver.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Paul Spencer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | // module.exports = require("./build/Debug/mapserver.node"); 18 | module.exports = require("./build/Release/mapserver.node"); 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.4.4" 4 | env: 5 | - MAPSERVER_COMMIT=master MAPSERVER_FORK=mapserver # mapserver master 6 | - MAPSERVER_COMMIT=rel-6-4-1 MAPSERVER_FORK=mapserver # mapserver master 7 | before_install: 8 | - mkdir tmp 9 | - cd tmp 10 | - wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.19.tar.bz2 11 | - tar xjf harfbuzz-0.9.19.tar.bz2 12 | - cd harfbuzz-0.9.19 13 | - ./configure --without-cairo --without-glib --without-icu 14 | - make -j3 15 | - sudo make install && sudo ldconfig 16 | - cd ../.. 17 | - sudo apt-get update -qq 18 | - sudo apt-get install -qq libfribidi-dev libpng12-dev libjpeg-dev libgif-dev libgd2-noxpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev 19 | - sh ./tools/install-deps.sh /tmp $MAPSERVER_FORK $MAPSERVER_COMMIT # install the dependencies 20 | - export CXX="g++ -I/tmp/mapserver -I/tmp/mapserver/build -L/tmp/mapserver-install/lib -lmapserver" 21 | - export LD_LIBRARY_PATH=/tmp/mapserver-install/lib:${LD_LIBRARY_PATH} 22 | - export PATH=/tmp/mapserver-install/bin:${PATH} # ensure `node-gyp` can find `mapserver-config` -------------------------------------------------------------------------------- /examples/mapserv.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mapserv 6 | 7 | 24 | 36 | 37 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /src/utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __NODE_MAPSERVER_UTILS_H__ 2 | #define __NODE_MAPSERVER_UTILS_H__ 3 | 4 | #define REPLACE_STRING(TARGET, VALUE) \ 5 | if (VALUE->IsString()) { \ 6 | msFree(TARGET); \ 7 | TARGET = strdup(*v8::String::Utf8Value((VALUE)->ToString())); \ 8 | } 9 | 10 | #define STRCMP(A, B) \ 11 | !std::strcmp(*v8::String::Utf8Value(A), B) 12 | 13 | #define ISSTR(INFO, N) \ 14 | (INFO.Length() > N && INFO[N]->IsString()) 15 | 16 | #define ISNUMERIC(INFO, N) \ 17 | (INFO.Length() > N && INFO[N]->IsNumber()) 18 | 19 | #define TOSTR(VALUE) (*v8::String::Utf8Value((VALUE)->ToString())) 20 | 21 | #define RO_ATTR(tpl, name, get) \ 22 | Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New(name).ToLocalChecked(), get); 23 | 24 | #define RW_ATTR(tpl, name, get, set) \ 25 | Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New(name).ToLocalChecked(), get, set); 26 | 27 | #define NODE_MAPSERVER_DEFINE_CONSTANT(t, n, v) \ 28 | (t)->Set(Nan::New(n).ToLocalChecked(), Nan::New(v)); 29 | 30 | #endif -------------------------------------------------------------------------------- /src/ms_map.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_MS_MAP_H 2 | #define _NODE_MS_MAP_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "ms_error.hpp" 9 | #include "ms_layer.hpp" 10 | #include "ms_layers.hpp" 11 | #include "ms_outputformat.hpp" 12 | #include "ms_rect.hpp" 13 | #include "ms_projection.hpp" 14 | #include "ms_hashtable.hpp" 15 | #include "utils.hpp" 16 | 17 | class MSMap: public Nan::ObjectWrap { 18 | public: 19 | static Nan::Persistent constructor; 20 | static void Initialize(v8::Local target); 21 | static NAN_METHOD(New); 22 | static v8::Local NewInstance(mapObj *map); 23 | 24 | static NAN_METHOD(Clone); 25 | static NAN_METHOD(SelectOutputFormat); 26 | static NAN_METHOD(SetExtent); 27 | static NAN_METHOD(DrawMap); 28 | static NAN_METHOD(Save); 29 | static void EIO_DrawMap(uv_work_t* req); 30 | static void EIO_AfterDrawMap(uv_work_t* req); 31 | 32 | static NAN_METHOD(Recompute); 33 | static NAN_METHOD(InsertLayer); 34 | static NAN_METHOD(SetSymbolSet); 35 | static NAN_METHOD(GetLabelCache); 36 | 37 | // static Handle Copy (const Arguments& args); 38 | static NAN_GETTER(PropertyGetter); 39 | static NAN_SETTER(PropertySetter); 40 | 41 | MSMap(); 42 | MSMap(mapObj *map); 43 | inline mapObj *get() { return this_; } 44 | mapObj *this_; 45 | 46 | MSLayers *layers_; 47 | MSRect *extent; 48 | MSOutputFormat *outputformat; 49 | // labelCacheObj labelcache; 50 | 51 | private: 52 | ~MSMap(); 53 | 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /tools/install-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## 4 | # Install a checkout of mapserver 5 | # 6 | # This is used by Travis-CI for installing a version of mapserver against which 7 | # node-mapserv can be built and tested. 8 | 9 | die() { 10 | if [ -n "${1}" ]; then 11 | echo $1 12 | fi 13 | exit 1; 14 | } 15 | 16 | PREFIX=$1 # the directory to install into 17 | MAPSERVER_FORK=$2 # mandatory git account name for fork 18 | MAPSERVER_COMMIT=$3 # the commit id to checkout (optional) 19 | 20 | if [ -z "${PREFIX}" ]; then 21 | die "usage: install-deps.sh PREFIX MAPSERVER_FORK [ MAPSERVER_COMMIT ]" 22 | fi 23 | if [ -z "${MAPSERVER_FORK}" ]; then 24 | die "usage: install-deps.sh PREFIX MAPSERVER_FORK [ MAPSERVER_COMMIT ]" 25 | fi 26 | 27 | # clone the mapserver repository 28 | git clone https://github.com/$MAPSERVER_FORK/mapserver.git $PREFIX/mapserver || die "Git clone failed" 29 | cd ${PREFIX}/mapserver || die "Cannot cd to ${PREFIX}/mapserver" 30 | if [ -n "${MAPSERVER_COMMIT}" ]; then 31 | git checkout $MAPSERVER_COMMIT || die "Cannot checkout ${MAPSERVER_COMMIT}" 32 | fi 33 | 34 | # build and install mapserver 35 | mkdir build 36 | cd build 37 | cmake .. -DCMAKE_INSTALL_PREFIX=${PREFIX}/mapserver-install -DWITH_THREAD_SAFETY=1 -DWITH_PROJ=1 -DWITH_FCGI=0 -DWITH_GEOS=0 -DWITH_GDAL=0 -DWITH_OGR=0 -DWITH_WFS=0 -DWITH_WCS=0 -DWITH_WMS=0 || die "cmake failed" 38 | make || die "make failed" 39 | make install || die "make install failed" 40 | 41 | # point `npm` at the build 42 | npm config set mapserver:lib_dir ${PREFIX}/mapserver-install/lib 43 | npm config set mapserver:include_dir ${PREFIX}/mapserver -------------------------------------------------------------------------------- /tests/data/test.map: -------------------------------------------------------------------------------- 1 | MAP 2 | NAME GMAP_DEMO 3 | STATUS ON 4 | SIZE 600 300 5 | EXTENT -180 -90 180 90 6 | UNITS DD 7 | SHAPEPATH "./" 8 | IMAGECOLOR 255 255 255 9 | WEB 10 | METADATA 11 | "foo" "bar" 12 | END 13 | END 14 | PROJECTION 15 | "init=epsg:4326" 16 | END 17 | LAYER 18 | NAME "grid" 19 | METADATA 20 | "DESCRIPTION" "Grid" 21 | END 22 | TYPE LINE 23 | STATUS ON 24 | CLASS 25 | NAME "Graticule" 26 | COLOR 0 0 0 27 | LABEL 28 | COLOR 255 0 0 29 | TYPE BITMAP 30 | SIZE TINY 31 | POSITION AUTO 32 | PARTIALS FALSE 33 | BUFFER 2 34 | OUTLINECOLOR 255 255 255 35 | END 36 | END 37 | PROJECTION 38 | "init=epsg:4326" 39 | END 40 | GRID 41 | LABELFORMAT "DD" 42 | END 43 | END # Layer 44 | LAYER 45 | NAME "grid2" 46 | METADATA 47 | "DESCRIPTION" "Grid" 48 | END 49 | TYPE LINE 50 | STATUS ON 51 | CLASS 52 | NAME "Graticule" 53 | COLOR 0 0 0 54 | LABEL 55 | COLOR 255 0 0 56 | TYPE BITMAP 57 | SIZE TINY 58 | POSITION AUTO 59 | PARTIALS FALSE 60 | BUFFER 2 61 | OUTLINECOLOR 255 255 255 62 | END 63 | END 64 | PROJECTION 65 | "init=epsg:4326" 66 | END 67 | GRID 68 | LABELFORMAT "DD" 69 | END 70 | END # Layer 71 | LAYER 72 | PROJECTION 73 | "init=epsg:4326" 74 | END 75 | NAME prov_bound 76 | TYPE POLYGON 77 | STATUS ON 78 | DATA wgs_province 79 | CLASS 80 | LABEL 81 | MINDISTANCE 100 82 | TEXT "[NAME][NAME_E]" 83 | PRIORITY 1 84 | WRAP "*" 85 | SIZE TINY 86 | END 87 | NAME "Province" 88 | STYLE 89 | OUTLINECOLOR 120 120 120 90 | END 91 | END 92 | END 93 | END 94 | -------------------------------------------------------------------------------- /src/mapserver.hpp: -------------------------------------------------------------------------------- 1 | #ifndef NODE_MAPSERVER_H 2 | #define NODE_MAPSERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.hpp" 9 | 10 | #include "ms_error.hpp" 11 | #include "ms_layer.hpp" 12 | #include "ms_layers.hpp" 13 | #include "ms_map.hpp" 14 | #include "ms_outputformat.hpp" 15 | #include "ms_point.hpp" 16 | #include "ms_projection.hpp" 17 | #include "ms_rect.hpp" 18 | #include "ms_hashtable.hpp" 19 | // #include "ms_common.hpp" 20 | 21 | using namespace v8; 22 | using namespace node; 23 | 24 | namespace node_mapserver { 25 | 26 | static NAN_METHOD(getVersionInt) { 27 | Nan::HandleScope scope; 28 | int version = msGetVersionInt(); 29 | info.GetReturnValue().Set(version); 30 | } 31 | 32 | static NAN_METHOD(getVersion) { 33 | Nan::HandleScope scope; 34 | char * version = msGetVersion(); 35 | info.GetReturnValue().Set(Nan::New(version).ToLocalChecked()); 36 | } 37 | 38 | static NAN_METHOD(supportsThreads) { 39 | Nan::HandleScope scope; 40 | char * version = msGetVersion(); 41 | char const * regex = "SUPPORTS\\=THREADS"; 42 | int match; 43 | match = 0; 44 | if (msEvalRegex(regex, version) == MS_TRUE) { 45 | match = 1; 46 | } else { 47 | // discard the error reported by msEvalRegex saying that it failed 48 | msResetErrorList(); 49 | } 50 | info.GetReturnValue().Set(match); 51 | } 52 | 53 | static NAN_METHOD(resetErrorList) { 54 | msResetErrorList(); 55 | } 56 | 57 | static NAN_METHOD(getError) { 58 | Nan::HandleScope scope; 59 | errorObj *err = msGetErrorObj(); 60 | info.GetReturnValue().Set(MSError::NewInstance(err)); 61 | } 62 | } 63 | 64 | #endif -------------------------------------------------------------------------------- /tests/data/gmap/data/fedlimit.dbf: -------------------------------------------------------------------------------- 1 | d AqFNODE_N TNODE_N LPOLY_N RPOLY_N LENGTHNFEDLIMIT_N FEDLIMIT_IN F_CODEN F_TYPEC 2 1 3 1 498100.688 1 1 30International 3 1 1 2 2558032.500 2 2 30International 3 1 2 3 2130836.500 3 3 30Fishing Limit 4 2 3 1 2565734.750 4 4 30Canada/Greenland 5 4 3 1 628662.313 5 5 30Fishing Limit 6 3 1 3 2730083.750 6 6 30International 6 8 3 1 1849150.000 7 7 30Fishing Limit 7 7 4 3 993602.938 8 8 30International 9 5 3 1 3132185.750 9 9 30Fishing Limit 8 10 3 1 4498442.500 10 10 30International 11 9 0 0 489035.156 11 11 30International 10 12 0 0 1606996.250 12 12 30International 12 11 0 0 69407.242 13 13 30Fishing Limit  -------------------------------------------------------------------------------- /tests/data/gmap/etc/symbols.sym: -------------------------------------------------------------------------------- 1 | SYMBOLSET 2 | Symbol 3 | Name 'tent' 4 | Type VECTOR 5 | Filled TRUE 6 | Points 7 | 0 1 8 | .5 0 9 | 1 1 10 | .75 1 11 | .5 .5 12 | .25 1 13 | 0 1 14 | END 15 | END 16 | 17 | Symbol 18 | Name 'star' 19 | Type VECTOR 20 | Filled TRUE 21 | Points 22 | 0 .375 23 | .35 .375 24 | .5 0 25 | .65 .375 26 | 1 .375 27 | .75 .625 28 | .875 1 29 | .5 .75 30 | .125 1 31 | .25 .625 32 | END 33 | END 34 | 35 | Symbol 36 | Name 'triangle' 37 | Type VECTOR 38 | Filled TRUE 39 | Points 40 | 0 1 41 | .5 0 42 | 1 1 43 | 0 1 44 | END 45 | END 46 | 47 | Symbol 48 | Name 'square' 49 | Type VECTOR 50 | Filled TRUE 51 | Points 52 | 0 1 53 | 0 0 54 | 1 0 55 | 1 1 56 | 0 1 57 | END 58 | END 59 | 60 | Symbol 61 | Name 'plus' 62 | Type VECTOR 63 | Points 64 | .5 0 65 | .5 1 66 | -99 -99 67 | 0 .5 68 | 1 .5 69 | END 70 | END 71 | 72 | Symbol 73 | Name 'cross' 74 | Type VECTOR 75 | Points 76 | 0 0 77 | 1 1 78 | -99 -99 79 | 0 1 80 | 1 0 81 | END 82 | END 83 | 84 | Symbol 85 | Name 'circle' 86 | Type ELLIPSE 87 | Filled TRUE 88 | Points 89 | 1 1 90 | END 91 | END 92 | 93 | 94 | Symbol 95 | Type VECTOR 96 | TRANSPARENT 0 97 | Points 98 | 0 1 99 | 1 1 100 | END 101 | END 102 | 103 | Symbol 104 | Type VECTOR 105 | TRANSPARENT 0 106 | Points 107 | 1 0 108 | 1 1 109 | END 110 | END 111 | 112 | Symbol 113 | Type VECTOR 114 | TRANSPARENT 0 115 | Points 116 | 0 0 117 | 1 1 118 | END 119 | END 120 | 121 | Symbol 122 | Type VECTOR 123 | TRANSPARENT 0 124 | Points 125 | 0 1 126 | 1 0 127 | END 128 | END 129 | 130 | Symbol 131 | Type VECTOR 132 | Points 133 | 0 1 134 | 1 0 135 | -99 -99 136 | 0 0 137 | 1 1 138 | END 139 | END 140 | 141 | Symbol 142 | Type ELLIPSE 143 | Filled TRUE 144 | Points 145 | 1 1 146 | END 147 | END 148 | 149 | -------------------------------------------------------------------------------- /src/ms_hashtable.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_hashtable.hpp" 2 | 3 | Nan::Persistent MSHashTable::constructor; 4 | 5 | void MSHashTable::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSHashTable::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("Hashtable").ToLocalChecked()); 9 | 10 | Nan::SetNamedPropertyHandler( 11 | tpl->InstanceTemplate() 12 | , NamedPropertyGetter 13 | , NamedPropertySetter 14 | , NULL 15 | , NULL 16 | , NULL); 17 | 18 | target->Set(Nan::New("Hashtable").ToLocalChecked(), tpl->GetFunction()); 19 | constructor.Reset(tpl); 20 | } 21 | 22 | MSHashTable::MSHashTable(hashTableObj *table) : ObjectWrap(), this_(table) {} 23 | 24 | MSHashTable::MSHashTable() : ObjectWrap(), this_(0) {} 25 | 26 | MSHashTable::~MSHashTable() { } 27 | 28 | NAN_METHOD(MSHashTable::New) 29 | { 30 | if (!info.IsConstructCall()) { 31 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 32 | return; 33 | } 34 | 35 | if (info[0]->IsExternal()) { 36 | v8::Local ext = info[0].As(); 37 | void *ptr = ext->Value(); 38 | MSHashTable *f = static_cast(ptr); 39 | f->Wrap(info.This()); 40 | info.GetReturnValue().Set(info.This()); 41 | return; 42 | } 43 | 44 | info.GetReturnValue().Set(info.This()); 45 | } 46 | 47 | v8::Local MSHashTable::NewInstance(hashTableObj *ptr) { 48 | Nan::EscapableHandleScope scope; 49 | MSHashTable* obj = new MSHashTable(); 50 | obj->this_ = ptr; 51 | v8::Local ext = Nan::New(obj); 52 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 53 | } 54 | 55 | NAN_PROPERTY_GETTER(MSHashTable::NamedPropertyGetter) { 56 | MSHashTable *table = Nan::ObjectWrap::Unwrap(info.Holder()); 57 | char *value = msLookupHashTable(table->this_, TOSTR(property)); 58 | if (value == NULL){ 59 | info.GetReturnValue().Set(Nan::Undefined()); 60 | return; 61 | } 62 | info.GetReturnValue().Set(Nan::New(value).ToLocalChecked()); 63 | } 64 | 65 | NAN_PROPERTY_SETTER(MSHashTable::NamedPropertySetter) { 66 | MSHashTable *table = Nan::ObjectWrap::Unwrap(info.Holder()); 67 | msInsertHashTable(table->this_, *v8::String::Utf8Value(property), TOSTR(value)); 68 | info.GetReturnValue().Set(value); 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/ms_layers.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_layers.hpp" 2 | #include "ms_layer.hpp" 3 | 4 | Nan::Persistent MSLayers::constructor; 5 | 6 | void MSLayers::Initialize(v8::Local target) { 7 | v8::Local tpl = Nan::New(MSLayers::New); 8 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 9 | tpl->SetClassName(Nan::New("Layers").ToLocalChecked()); 10 | 11 | Nan::SetIndexedPropertyHandler(tpl->InstanceTemplate(), IndexGetter, NULL, NULL, NULL, NULL); 12 | Nan::SetNamedPropertyHandler(tpl->InstanceTemplate(), NamedGetter, NULL, NULL, NULL, NULL); 13 | 14 | target->Set(Nan::New("Layers").ToLocalChecked(), tpl->GetFunction()); 15 | constructor.Reset(tpl); 16 | } 17 | 18 | MSLayers::MSLayers(mapObj *map) : ObjectWrap(), this_(map) {} 19 | 20 | MSLayers::MSLayers() : ObjectWrap(), this_(0) {} 21 | 22 | MSLayers::~MSLayers() { } 23 | 24 | NAN_METHOD(MSLayers::New) { 25 | MSLayers *obj; 26 | 27 | if (!info.IsConstructCall()) { 28 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 29 | return; 30 | } 31 | 32 | if (info[0]->IsExternal()) { 33 | v8::Local ext = info[0].As(); 34 | void* ptr = ext->Value(); 35 | obj = static_cast(ptr); 36 | obj->Wrap(info.This()); 37 | info.GetReturnValue().Set(info.This()); 38 | return; 39 | } 40 | info.GetReturnValue().Set(info.This()); 41 | } 42 | 43 | v8::Local MSLayers::NewInstance(mapObj *ptr) { 44 | Nan::EscapableHandleScope scope; 45 | MSLayers* obj = new MSLayers(); 46 | obj->this_ = ptr; 47 | v8::Local ext = Nan::New(obj); 48 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 49 | } 50 | 51 | NAN_INDEX_GETTER(MSLayers::IndexGetter) { 52 | MSLayers *layers = Nan::ObjectWrap::Unwrap(info.Holder()); 53 | 54 | if ((int)index < layers->this_->numlayers) { 55 | info.GetReturnValue().Set(MSLayer::NewInstance(GET_LAYER(layers->this_, index))); 56 | } 57 | } 58 | 59 | NAN_PROPERTY_GETTER(MSLayers::NamedGetter) { 60 | MSLayers *layers = Nan::ObjectWrap::Unwrap(info.Holder()); 61 | if (STRCMP(property, "length")) { 62 | info.GetReturnValue().Set(layers->this_->numlayers); 63 | } else { 64 | int i; 65 | for (i=0; ithis_->numlayers; i++) { 66 | if (STRCMP(property, GET_LAYER(layers->this_, i)->name)) { 67 | info.GetReturnValue().Set(MSLayer::NewInstance(GET_LAYER(layers->this_, i))); 68 | } 69 | } 70 | } 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /tools/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | ############################################################################## 4 | # Copyright (c) 2012, GeoData Institute (www.geodata.soton.ac.uk) 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # - Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # - Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | # POSSIBILITY OF SUCH DAMAGE. 28 | ############################################################################## 29 | 30 | """ 31 | Output mapserver configuration information to `node-gyp` 32 | 33 | Configuration options are retrieved from environment variables set using `npm 34 | config set`. This allows for a simple `npm install mapserv` to work. 35 | """ 36 | 37 | from optparse import OptionParser 38 | import os 39 | 40 | def get_lib_dir(): 41 | return os.environ.get('npm_config_mapserver_lib_dir', '') 42 | 43 | parser = OptionParser() 44 | parser.add_option("--include", 45 | action="store_true", default=False, 46 | help="output the mapserver include path") 47 | 48 | parser.add_option("--ldflags", 49 | action="store_true", default=False, 50 | help="output the mapserver library rpath option") 51 | 52 | (options, args) = parser.parse_args() 53 | 54 | if options.include: 55 | print os.environ.get('npm_config_mapserver_include_dir', '') 56 | 57 | if options.ldflags: 58 | # write the library path into the resulting binary 59 | lib_dir = get_lib_dir() 60 | if lib_dir: 61 | print "-Wl,-rpath=%s -L%s" % (lib_dir, lib_dir) 62 | print '-Wl,--no-as-needed,-lmapserver' -------------------------------------------------------------------------------- /tests/data/gmap/etc/symbols.txt: -------------------------------------------------------------------------------- 1 | SYMBOLSET 2 | SYMBOL 3 | NAME "tent" 4 | TYPE VECTOR 5 | FILLED TRUE 6 | POINTS 7 | 0 1 8 | .5 0 9 | 1 1 10 | .75 1 11 | .5 .5 12 | .25 1 13 | 0 1 14 | END 15 | END 16 | 17 | SYMBOL 18 | NAME "star" 19 | TYPE VECTOR 20 | FILLED TRUE 21 | POINTS 22 | 0 .375 23 | .35 .375 24 | .5 0 25 | .65 .375 26 | 1 .375 27 | .75 .625 28 | .875 1 29 | .5 .75 30 | .125 1 31 | .25 .625 32 | END 33 | END 34 | 35 | SYMBOL 36 | NAME "triangle" 37 | TYPE VECTOR 38 | FILLED TRUE 39 | POINTS 40 | 0 1 41 | .5 0 42 | 1 1 43 | 0 1 44 | END 45 | END 46 | 47 | SYMBOL 48 | NAME "square" 49 | TYPE VECTOR 50 | FILLED TRUE 51 | POINTS 52 | 0 1 53 | 0 0 54 | 1 0 55 | 1 1 56 | 0 1 57 | END 58 | END 59 | 60 | SYMBOL 61 | NAME "plus" 62 | TYPE VECTOR 63 | POINTS 64 | .5 0 65 | .5 1 66 | -99 -99 67 | 0 .5 68 | 1 .5 69 | END 70 | END 71 | 72 | SYMBOL 73 | NAME "cross" 74 | TYPE VECTOR 75 | POINTS 76 | 0 0 77 | 1 1 78 | -99 -99 79 | 0 1 80 | 1 0 81 | END 82 | END 83 | 84 | SYMBOL 85 | NAME "circle" 86 | TYPE ELLIPSE 87 | FILLED TRUE 88 | POINTS 89 | 1 1 90 | END 91 | END 92 | 93 | 94 | SYMBOL 95 | NAME "line_180" 96 | TYPE VECTOR 97 | TRANSPARENT 0 98 | POINTS 99 | 0 1 100 | 1 1 101 | END 102 | END 103 | 104 | SYMBOL 105 | NAME "line_90" 106 | TYPE VECTOR 107 | TRANSPARENT 0 108 | POINTS 109 | 1 0 110 | 1 1 111 | END 112 | END 113 | 114 | SYMBOL 115 | NAME "line_135" 116 | TYPE VECTOR 117 | TRANSPARENT 0 118 | POINTS 119 | 0 0 120 | 1 1 121 | END 122 | END 123 | 124 | SYMBOL 125 | NAME "line_45" 126 | TYPE VECTOR 127 | TRANSPARENT 0 128 | POINTS 129 | 0 1 130 | 1 0 131 | END 132 | END 133 | 134 | END 135 | 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/pagameba/node-mapserver.png?branch=master)](https://travis-ci.org/pagameba/node-mapserver) 2 | 3 | # Overview 4 | 5 | node-mapserver is an MIT-licensed node.js extension to the [mapserver](http://mapserver.org/ "MapServer") open source web mapping engine. It allows you to access all the mapserver goodness for rendering map images in a node.js environment, allowing you to build high-performance, low-latency map servers. 6 | 7 | ## Getting node-mapserver 8 | 9 | Get the source from git and build it on your system against an existing mapserver installation. You will need to have already installed mapserver plus the development headers using your system's package management tools or built mapserver from source. 10 | 11 | See the (MapServer)[http://mapserver.org] website for more details. 12 | 13 | ### Step 1 - Use The Source, Luke 14 | 15 | ``` 16 | git clone git://github.com/pagameba/node-mapserver.git 17 | cd node-mapserver 18 | ``` 19 | 20 | ### Step 2 - Make It So, #1 21 | 22 | on linux, you will need to have installed mapserver package (and possibly the -devel package too) using your package management system, or have built it yourself. If you've installed in, find out where it is installed (perhaps /usr/local/) and use those paths. If you've built it yourself, you can probably figure out how you need to change this to work for you. 23 | 24 | ``` 25 | CXX="g++ -I//include -L//lib -lmapserver" node-gyp configure build 26 | ``` 27 | 28 | *NOTE* If your GD library is not 'installed' in a findable location you can add it using -I/ 29 | 30 | *NOTE* If you are building against a mapserver build directory, use -I/ 31 | 32 | on osx with [kyngchaos](http://kyngchaos.com) frameworks you will still need a copy of the mapserver source from a tarball or svn appropriate to the version you have installed because the framework doesn't (as of the last time I checked) include headers: 33 | 34 | ``` 35 | CXX="g++ -I/" -framework MapServer" node-gyp configure build 36 | ``` 37 | 38 | *NOTE* you will probably get build warnings about the framework being ignored in the compile step, this is normal since the framework only gets used in the linking step. 39 | 40 | Building on another system? Find a problem building on your system? Submit an issue and let me know what the problem is or how you solved it so we can make this more awesome for everyone. 41 | 42 | ### Step 3 - Test, Test, Test 43 | 44 | ``` 45 | node tests/tests.js 46 | ``` 47 | 48 | ## Using node-mapserver 49 | 50 | See the examples provided in the `examples` directory, check out the tests and read up on specific methods in the [documentation](https://github.com/pagameba/node-mapserver/wiki/Api-documentation) 51 | 52 | ## Documentation 53 | 54 | Extensive API documentation is available [in the wiki](https://github.com/pagameba/node-mapserver/wiki/Api-documentation) 55 | -------------------------------------------------------------------------------- /src/ms_error.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_error.hpp" 2 | 3 | Nan::Persistent MSError::constructor; 4 | 5 | void MSError::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New (MSError::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("MSError").ToLocalChecked()); 9 | 10 | Nan::SetNamedPropertyHandler( 11 | tpl->InstanceTemplate() 12 | , MSError::NamedPropertyGetter 13 | , NULL 14 | , MSError::NamedPropertyQuery 15 | , NULL 16 | , MSError::NamedPropertyEnumerator); 17 | 18 | target->Set(Nan::New("MSError").ToLocalChecked(), tpl->GetFunction()); 19 | constructor.Reset(tpl); 20 | } 21 | 22 | MSError::MSError(errorObj *err) : Nan::ObjectWrap(), this_(err) { } 23 | 24 | MSError::MSError() : Nan::ObjectWrap(), this_(0) { } 25 | 26 | MSError::~MSError() { } 27 | 28 | NAN_METHOD(MSError::New) 29 | { 30 | if (!info.IsConstructCall()) { 31 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 32 | return; 33 | } 34 | 35 | if (info[0]->IsExternal()) { 36 | v8::Local ext = info[0].As(); 37 | void *ptr = ext->Value(); 38 | MSError *f = static_cast(ptr); 39 | f->Wrap(info.This()); 40 | info.GetReturnValue().Set(info.This()); 41 | return; 42 | } 43 | 44 | info.GetReturnValue().Set(info.This()); 45 | } 46 | 47 | v8::Local MSError::NewInstance(errorObj *err_ptr) { 48 | Nan::EscapableHandleScope scope; 49 | MSError* err = new MSError(); 50 | err->this_ = err_ptr; 51 | v8::Local ext = Nan::New(err); 52 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 53 | } 54 | 55 | NAN_PROPERTY_GETTER(MSError::NamedPropertyGetter) { 56 | MSError *err = Nan::ObjectWrap::Unwrap(info.Holder()); 57 | 58 | if (STRCMP(property, "code")) { 59 | info.GetReturnValue().Set(err->this_->code); 60 | } else if (STRCMP(property, "message")) { 61 | info.GetReturnValue().Set(Nan::New(err->this_->message).ToLocalChecked()); 62 | } else if (STRCMP(property, "routine")) { 63 | info.GetReturnValue().Set(Nan::New(err->this_->routine).ToLocalChecked()); 64 | } 65 | } 66 | 67 | NAN_PROPERTY_QUERY(MSError::NamedPropertyQuery) { 68 | if (STRCMP(property, "code")) { 69 | info.GetReturnValue().Set(Nan::New(v8::None)); 70 | } else if (STRCMP(property, "message")) { 71 | info.GetReturnValue().Set(Nan::New(v8::None)); 72 | } else if (STRCMP(property, "routine")) { 73 | info.GetReturnValue().Set(Nan::New(v8::None)); 74 | } else { 75 | info.GetReturnValue().Set(Nan::New(v8::DontEnum)); 76 | } 77 | } 78 | 79 | NAN_PROPERTY_ENUMERATOR(MSError::NamedPropertyEnumerator) { 80 | v8::Local env = Nan::New(4); 81 | Nan::Set(env, 0, Nan::New("code").ToLocalChecked()); 82 | Nan::Set(env, 2, Nan::New("message").ToLocalChecked()); 83 | Nan::Set(env, 3, Nan::New("routine").ToLocalChecked()); 84 | info.GetReturnValue().Set(env); 85 | } -------------------------------------------------------------------------------- /tests/data/gmap/htdocs/gmap75_key.map: -------------------------------------------------------------------------------- 1 | # 2 | # Start of map file 3 | # 4 | # $Id: gmap75_key.map,v 1.2 2003/07/23 02:31:27 daniel Exp $ 5 | # 6 | NAME DEMO 7 | STATUS ON 8 | SIZE 120 90 9 | SHADESET symbols/shade.sym 10 | MARKERSET symbols/marker.sym 11 | LINESET symbols/line.sym 12 | EXTENT -2750560 -936639 3583870 4673130 13 | UNITS METERS 14 | SHAPEPATH "../data" 15 | IMAGECOLOR 255 255 255 16 | 17 | #LABELOVERLAP FALSE 18 | 19 | # 20 | # Start of web interface definition 21 | # 22 | WEB 23 | # HEADER demo_header.html 24 | # TEMPLATE demo.html 25 | MINSCALE 750000 26 | MAXSCALE 30000000 27 | # 28 | # On Windows systems, /tmp and /tmp/ms_tmp/ should be created at the root 29 | # of the drive where the .MAP file resides. 30 | # 31 | IMAGEPATH "/ms4w/tmp/ms_tmp/" 32 | IMAGEURL "/ms_tmp/" 33 | # LOG "/tmp/gmap.log" 34 | END 35 | 36 | # 37 | # Start of reference map 38 | # 39 | REFERENCE 40 | IMAGE images/keymap75.gif 41 | EXTENT -2771317 -1715475 3633940 4689781 42 | STATUS ON 43 | COLOR -1 -1 -1 44 | OUTLINECOLOR 255 0 0 45 | END 46 | 47 | # 48 | # Start of legend 49 | # 50 | LEGEND 51 | KEYSIZE 18 12 52 | LABEL 53 | TYPE BITMAP 54 | SIZE MEDIUM 55 | COLOR 0 0 89 56 | END 57 | STATUS ON 58 | END 59 | 60 | # 61 | # Start of scalebar 62 | # 63 | SCALEBAR 64 | IMAGECOLOR 255 255 255 65 | LABEL 66 | COLOR 0 0 0 67 | SIZE SMALL 68 | END 69 | SIZE 150 5 70 | COLOR 255 255 255 71 | BACKGROUNDCOLOR 0 0 0 72 | OUTLINECOLOR 0 0 0 73 | UNITS kilometers 74 | INTERVALS 5 75 | STATUS ON 76 | END 77 | 78 | # 79 | # Start of layer definitions 80 | # 81 | 82 | LAYER 83 | NAME province 84 | TYPE POLYGON 85 | STATUS ON 86 | DATA province 87 | CLASS 88 | NAME "Province" 89 | OUTLINECOLOR 0 0 0 90 | COLOR 190 190 190 91 | END 92 | END 93 | 94 | LAYER 95 | NAME land_fn 96 | TYPE POLYGON 97 | STATUS ON 98 | DATA land_fn 99 | CLASS 100 | NAME "Foreign Lands" 101 | COLOR 220 220 220 102 | END 103 | END 104 | 105 | LAYER 106 | NAME drainage 107 | TYPE POLYGON 108 | STATUS OFF 109 | DATA drainage 110 | CLASS 111 | NAME "Streams" 112 | COLOR 159 209 255 113 | END 114 | END 115 | 116 | 117 | LAYER 118 | NAME road 119 | TYPE LINE 120 | STATUS OFF 121 | DATA road 122 | CLASS 123 | NAME "road" 124 | COLOR 255 0 0 125 | END 126 | 127 | END # Layer 128 | 129 | LAYER 130 | NAME park 131 | TYPE POLYGON 132 | STATUS OFF 133 | DATA park 134 | CLASS 135 | NAME "Park" 136 | COLOR 0 255 0 137 | END 138 | 139 | END # Layer 140 | 141 | LAYER 142 | NAME "grid" 143 | TYPE LINE 144 | STATUS OFF 145 | DATA "grid" 146 | CLASS 147 | NAME "Grid" 148 | COLOR 0 0 0 149 | END 150 | 151 | END # Layer 152 | 153 | LAYER 154 | NAME popplace 155 | TYPE POINT 156 | STATUS OFF 157 | DATA popplace 158 | LabelItem "Name" 159 | Classitem "Pop_range" 160 | CLASS 161 | expression "6" 162 | SYMBOL 7 163 | SIZE 5 164 | NAME "road" 165 | COLOR 0 0 0 166 | END 167 | 168 | END # Layer 169 | 170 | END # Map File 171 | 172 | -------------------------------------------------------------------------------- /src/ms_projection.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_projection.hpp" 2 | 3 | Nan::Persistent MSProjection::constructor; 4 | 5 | void MSProjection::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSProjection::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("Projection").ToLocalChecked()); 9 | 10 | RO_ATTR(tpl, "units", Units); 11 | RW_ATTR(tpl, "projString", ProjString, SetProjString); 12 | 13 | target->Set(Nan::New("Projection").ToLocalChecked(), tpl->GetFunction()); 14 | constructor.Reset(tpl); 15 | } 16 | 17 | MSProjection::MSProjection(projectionObj *proj) : ObjectWrap(), this_(proj) { 18 | owner = false; 19 | } 20 | 21 | MSProjection::MSProjection() : ObjectWrap(), this_(0) { owner = false; } 22 | 23 | MSProjection::~MSProjection() { 24 | if (this_ && owner == true) { 25 | msFreeProjection(this_); 26 | free(this_); 27 | owner = false; 28 | } 29 | } 30 | 31 | NAN_METHOD(MSProjection::New) { 32 | MSProjection *obj; 33 | 34 | if (!info.IsConstructCall()) { 35 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 36 | return; 37 | } 38 | 39 | if (info[0]->IsExternal()) { 40 | v8::Local ext = info[0].As(); 41 | void* ptr = ext->Value(); 42 | obj = static_cast(ptr); 43 | obj->Wrap(info.This()); 44 | info.GetReturnValue().Set(info.This()); 45 | return; 46 | } 47 | 48 | if (info.Length() > 1 || info.Length() < 1 || !info[0]->IsString()) { 49 | Nan::ThrowTypeError("requires one argument: a projection definition string"); 50 | return; 51 | } 52 | 53 | int status; 54 | projectionObj *proj=NULL; 55 | 56 | proj = (projectionObj *)malloc(sizeof(projectionObj)); 57 | if(!proj) { 58 | info.GetReturnValue().Set(info.This()); 59 | return; 60 | } 61 | msInitProjection(proj); 62 | 63 | status = msLoadProjectionString(proj, TOSTR(info[0])); 64 | if(status == -1) { 65 | msFreeProjection(proj); 66 | free(proj); 67 | info.GetReturnValue().Set(info.This()); 68 | return; 69 | } 70 | 71 | obj = new MSProjection(proj); 72 | obj->owner = true; 73 | obj->Wrap(info.This()); 74 | info.GetReturnValue().Set(info.This()); 75 | } 76 | 77 | v8::Local MSProjection::NewInstance(projectionObj *ptr) { 78 | Nan::EscapableHandleScope scope; 79 | MSProjection* obj = new MSProjection(); 80 | obj->this_ = ptr; 81 | v8::Local ext = Nan::New(obj); 82 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 83 | } 84 | 85 | NAN_GETTER(MSProjection::Units) { 86 | MSProjection *proj = Nan::ObjectWrap::Unwrap(info.Holder()); 87 | int units = GetMapserverUnitUsingProj(proj->this_); 88 | info.GetReturnValue().Set(units); 89 | } 90 | 91 | NAN_GETTER(MSProjection::ProjString) { 92 | MSProjection *proj = Nan::ObjectWrap::Unwrap(info.Holder()); 93 | info.GetReturnValue().Set(Nan::New(msGetProjectionString(proj->this_)).ToLocalChecked()); 94 | } 95 | 96 | NAN_SETTER(MSProjection::SetProjString) { 97 | MSProjection *proj = Nan::ObjectWrap::Unwrap(info.Holder()); 98 | if (!value->IsString()) 99 | { 100 | Nan::ThrowTypeError("projection string value must be a string"); 101 | return; 102 | } 103 | msLoadProjectionString(proj->this_, TOSTR(value)); 104 | } 105 | -------------------------------------------------------------------------------- /src/ms_outputformat.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_outputformat.hpp" 2 | 3 | Nan::Persistent MSOutputFormat::constructor; 4 | 5 | void MSOutputFormat::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSOutputFormat::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("OutputFormat").ToLocalChecked()); 9 | 10 | RO_ATTR(tpl, "name", PropertyGetter); 11 | RO_ATTR(tpl, "mimetype", PropertyGetter); 12 | RO_ATTR(tpl, "driver", PropertyGetter); 13 | RO_ATTR(tpl, "extension", PropertyGetter); 14 | RO_ATTR(tpl, "renderer", PropertyGetter); 15 | RO_ATTR(tpl, "imagemode", PropertyGetter); 16 | RO_ATTR(tpl, "transparent", PropertyGetter); 17 | 18 | target->Set(Nan::New("OutputFormat").ToLocalChecked(), tpl->GetFunction()); 19 | constructor.Reset(tpl); 20 | } 21 | 22 | MSOutputFormat::MSOutputFormat(outputFormatObj *of) : ObjectWrap(), this_(of) {} 23 | 24 | MSOutputFormat::MSOutputFormat() : ObjectWrap(), this_(0) {} 25 | 26 | MSOutputFormat::~MSOutputFormat() { } 27 | 28 | NAN_METHOD(MSOutputFormat::New) { 29 | MSOutputFormat *obj; 30 | 31 | if (!info.IsConstructCall()) { 32 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 33 | } 34 | 35 | if (info[0]->IsExternal()) { 36 | v8::Local ext = info[0].As(); 37 | void* ptr = ext->Value(); 38 | obj = static_cast(ptr); 39 | obj->Wrap(info.This()); 40 | info.GetReturnValue().Set(info.This()); 41 | return; 42 | } 43 | 44 | if (!ISSTR(info, 0) || !ISSTR(info,1)) { 45 | Nan::ThrowTypeError("MSOutputFormat requires two string arguments"); 46 | } 47 | 48 | outputFormatObj *format = msCreateDefaultOutputFormat(NULL, TOSTR(info[0]), TOSTR(info[1])); 49 | 50 | /* in the case of unsupported formats, msCreateDefaultOutputFormat 51 | should return NULL */ 52 | if (!format) { 53 | msSetError(MS_MISCERR, "Unsupported format driver: %s", 54 | "outputFormatObj()", TOSTR(info[0])); 55 | info.GetReturnValue().Set(info.This()); 56 | return; 57 | } 58 | 59 | msInitializeRendererVTable(format); 60 | 61 | /* Else, continue */ 62 | format->refcount++; 63 | format->inmapfile = MS_TRUE; 64 | 65 | obj = new MSOutputFormat(format); 66 | obj->Wrap(info.This()); 67 | info.GetReturnValue().Set(info.This()); 68 | } 69 | 70 | v8::Local MSOutputFormat::NewInstance(outputFormatObj *of_ptr) { 71 | Nan::EscapableHandleScope scope; 72 | MSOutputFormat* of = new MSOutputFormat(); 73 | of->this_ = of_ptr; 74 | v8::Local ext = Nan::New(of); 75 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 76 | } 77 | 78 | NAN_GETTER(MSOutputFormat::PropertyGetter) { 79 | MSOutputFormat *of = Nan::ObjectWrap::Unwrap(info.Holder()); 80 | 81 | if (STRCMP(property, "name")) { 82 | info.GetReturnValue().Set(Nan::New(of->this_->name).ToLocalChecked()); 83 | } else if (STRCMP(property, "mimetype")) { 84 | info.GetReturnValue().Set(Nan::New(of->this_->mimetype).ToLocalChecked()); 85 | } else if (STRCMP(property, "driver")) { 86 | info.GetReturnValue().Set(Nan::New(of->this_->driver).ToLocalChecked()); 87 | } else if (STRCMP(property, "renderer")) { 88 | info.GetReturnValue().Set(of->this_->renderer); 89 | } else if (STRCMP(property, "imagemode")) { 90 | info.GetReturnValue().Set(of->this_->imagemode); 91 | } else if (STRCMP(property, "transparent")) { 92 | info.GetReturnValue().Set(of->this_->transparent); 93 | } 94 | } -------------------------------------------------------------------------------- /tests/data/gmap/htdocs/gmap75_wfs.map: -------------------------------------------------------------------------------- 1 | # 2 | # Start of map file 3 | # 4 | # 5 | NAME WFS_server 6 | STATUS ON 7 | SIZE 400 300 8 | SYMBOLSET ../etc/symbols.sym 9 | ## ESPG:42304 extents: 10 | EXTENT -2200000 -712631 3072800 3840000 11 | UNITS METERS 12 | SHAPEPATH "../data" 13 | IMAGECOLOR 255 255 255 14 | FONTSET ../etc/fonts.txt 15 | 16 | 17 | # 18 | # Start of web interface definition 19 | # 20 | WEB 21 | # 22 | # On Windows systems, /tmp and /tmp/ms_tmp/ should be created at the root 23 | # of the drive where the .MAP file resides. 24 | # 25 | IMAGEPATH "/ms4w/tmp/ms_tmp/" 26 | IMAGEURL "/ms_tmp/" 27 | METADATA 28 | "wfs_title" "GMap WMS Demo Server" 29 | "wfs_onlineresource" "http://127.0.0.1/cgi-bin/mapserv.exe?MAP=/ms4w/apps/gmap/htdocs/gmap75_wfs.map" 30 | "wfs_srs" "EPSG:42304 EPSG:42101 EPSG:4269 EPSG:4326" 31 | "wfs_schemas_location" "http://ogc.dmsolutions.ca" 32 | END 33 | END 34 | 35 | PROJECTION 36 | "init=epsg:42304" 37 | END 38 | 39 | # 40 | # Start of reference map 41 | # 42 | REFERENCE 43 | IMAGE images/keymap.png 44 | #EPSG:42304 extents 45 | EXTENT -2200000 -712631 3072800 3840000 46 | STATUS ON 47 | COLOR -1 -1 -1 48 | OUTLINECOLOR 255 0 0 49 | SIZE 120 90 50 | END 51 | 52 | # 53 | # Start of legend 54 | # 55 | LEGEND 56 | KEYSIZE 18 12 57 | LABEL 58 | TYPE BITMAP 59 | SIZE MEDIUM 60 | COLOR 0 0 89 61 | END 62 | STATUS ON 63 | END 64 | 65 | # 66 | # Start of scalebar 67 | # 68 | SCALEBAR 69 | IMAGECOLOR 255 255 255 70 | LABEL 71 | COLOR 0 0 0 72 | SIZE SMALL 73 | END 74 | SIZE 200 5 75 | COLOR 255 255 255 76 | BACKGROUNDCOLOR 0 0 0 77 | OUTLINECOLOR 0 0 0 78 | UNITS kilometers 79 | INTERVALS 5 80 | STATUS ON 81 | END 82 | 83 | 84 | QUERYMAP 85 | STYLE HILITE 86 | COLOR 255 0 0 87 | END 88 | 89 | 90 | # 91 | # Start of layer definitions 92 | # 93 | 94 | 95 | LAYER 96 | NAME park 97 | METADATA 98 | "wfs_title" "Parks" 99 | "gml_include_items" "all" 100 | "gml_featureid" "PARK_" 101 | END 102 | TYPE POLYGON 103 | STATUS OFF 104 | DATA park 105 | PROJECTION 106 | "init=epsg:42304" 107 | END 108 | ## DUMP TRUE required for layer to be usable as WFS 109 | DUMP TRUE 110 | CLASS 111 | NAME "Parks" 112 | STYLE 113 | COLOR 200 255 0 114 | OUTLINECOLOR 120 120 120 115 | END 116 | TEMPLATE "ttt_query.html" 117 | END 118 | TOLERANCE 5 119 | END # Layer 120 | 121 | 122 | LAYER 123 | NAME popplace 124 | METADATA 125 | "wfs_title" "Cities" 126 | "gml_include_items" "all" 127 | "gml_featureid" "POPPLACE_" 128 | END 129 | TYPE POINT 130 | STATUS ON 131 | DATA popplace 132 | PROJECTION 133 | "init=epsg:42304" 134 | END 135 | ## DUMP TRUE required for layer to be usable as WFS 136 | DUMP TRUE 137 | CLASSITEM "Capital" 138 | CLASS 139 | EXPRESSION "1" 140 | TEMPLATE "ttt_query.html" 141 | NAME "Cities" 142 | LABEL 143 | COLOR 255 0 0 144 | FONT sans-italic 145 | TYPE truetype 146 | SIZE 8 147 | POSITION AUTO 148 | PARTIALS FALSE 149 | OUTLINECOLOR 255 255 255 150 | END 151 | STYLE 152 | SYMBOL 2 153 | SIZE 8 154 | COLOR 0 0 0 155 | END 156 | END 157 | CLASS 158 | EXPRESSION /2|3/ 159 | TEMPLATE "ttt_query.html" 160 | NAME "Cities" 161 | LABEL 162 | COLOR 0 0 0 163 | FONT sans 164 | TYPE truetype 165 | SIZE 8 166 | POSITION AUTO 167 | PARTIALS FALSE 168 | OUTLINECOLOR 255 255 255 169 | END 170 | STYLE 171 | SYMBOL 7 172 | SIZE 6 173 | COLOR 0 0 0 174 | END 175 | END 176 | TOLERANCE 5 177 | END # Layer 178 | 179 | 180 | END # Map File 181 | -------------------------------------------------------------------------------- /examples/mapserv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A simplified mapserv clone using node-mapserver. Only provides mode=map 3 | * support (and hence mode=map is not required in the url). Maps are 4 | * preconfigured and so map= is ignored in the url. Supported parameters are: 5 | * - layers= - space-separated list of layers to turn on, or all 6 | * for all layers 7 | * - mapext= - the geospatial extent of the map 8 | * image to draw 9 | * - mapsize= - the size of the map image to draw 10 | */ 11 | 12 | var util = require('util') 13 | , http = require("http") 14 | , url = require("url") 15 | , mapserver = require("../mapserver") 16 | , path = require("path") 17 | , fs = require('fs') 18 | , Cache = require('./cache').Cache 19 | ; 20 | 21 | var port = 8080; 22 | 23 | var maps = {}; 24 | 25 | var map_config = { 26 | gmap: __dirname + '/../tests/data/gmap/htdocs/gmap75.map' 27 | }; 28 | 29 | for (var key in map_config) { 30 | var mappath = map_config[key]; 31 | try { 32 | maps[key] = new mapserver.Map(mappath); 33 | } catch (e) { 34 | console.log(mapserver.getError()); 35 | } 36 | } 37 | 38 | var cache = new Cache(100000); 39 | 40 | http.createServer(function(request, response) { 41 | var parsed = url.parse(request.url, true); 42 | var components = parsed.pathname.split('/').splice(1); 43 | var page = components[0]; 44 | if (page == '') { 45 | // root, serve HTML up 46 | var html = path.normalize(path.join(__dirname,'mapserv.html')); 47 | fs.readFile(html, function(err, buffer) { 48 | if (!err) { 49 | response.writeHead(200, { 50 | 'Content-Type':'text/html' 51 | }); 52 | response.end(buffer); 53 | } else { 54 | response.writeHead(400, { 55 | 'Content-type':'text/html' 56 | }); 57 | response.end('File not found'); 58 | } 59 | }); 60 | } else if (page == 'favicon.ico') { 61 | var html = path.normalize(path.join(__dirname,'mapserv.ico')); 62 | fs.readFile(html, function(err, buffer) { 63 | if (!err) { 64 | response.writeHead(200, { 65 | 'Content-Type':'image/x-icon' 66 | }); 67 | response.end(buffer); 68 | } else { 69 | response.writeHead(400, { 70 | 'Content-type':'text/html' 71 | }); 72 | response.end('File not found'); 73 | } 74 | }); 75 | 76 | } else if (maps[page] != undefined) { 77 | var key = require('crypto').createHash('md5').update(parsed.search).digest('hex'); 78 | 79 | var o = cache.get(key); 80 | if (o) { 81 | response.writeHead(200, { 82 | 'Content-Type': o.data.mimetype 83 | }); 84 | response.end(o.data.buffer); 85 | 86 | } else { 87 | var map = maps[page].clone(); 88 | if (parsed.query.map_size) { 89 | var mapsize = parsed.query.map_size.split(' '); 90 | map.width = mapsize[0]; 91 | map.height = mapsize[1]; 92 | } 93 | if (parsed.query.mapext) { 94 | var extent = parsed.query.mapext.split(' ').map(function(n) { return parseFloat(n); }); 95 | if (extent.length == 4) { 96 | map.setExtent(extent[0], extent[1], extent[2], extent[3]); 97 | } 98 | } 99 | if (parsed.query.layers) { 100 | var layers = parsed.query.layers.split(' '); 101 | if (layers.length == 1 && layers[0] == 'all') { 102 | for (var i=0; i) 10 | * which means that there is a queue for 1 hit, a queue for 2-10, a queue for 11 | * 11-100 and so on. 12 | */ 13 | 14 | var Cache = function(max) { 15 | // hash for all objects so we can find them relatively quickly 16 | var cache = {}; 17 | 18 | /** 19 | * Class: Queue 20 | * manage a linked list of cache objects to a maximum size 21 | */ 22 | var Queue = function(max) { 23 | var n = 0, 24 | that = this, 25 | last = null; 26 | that.next = null; 27 | /** 28 | * Method: push 29 | * push an object at the head of the queue 30 | * 31 | * Parameters: 32 | * o - the object ot push 33 | * 34 | * Returns: an object displaced from the bottom of the queue if the queue 35 | * is full or null. 36 | */ 37 | this.push = function(o) { 38 | if (!o) return; 39 | if (that.next) { 40 | o.next = that.next; 41 | that.next = o; 42 | } else { 43 | o.next = null; 44 | last = o; 45 | } 46 | o.prev = that; 47 | o.q = this; 48 | n++; 49 | if (n>max) { 50 | return this.pop(); 51 | } 52 | }; 53 | /** 54 | * Method: pop 55 | * pull an object off the bottom of the queue and return it 56 | */ 57 | this.pop = function() { 58 | if (last) { 59 | n--; 60 | var o = last; 61 | last.prev.next = null; 62 | last = last.prev; 63 | return o; 64 | } 65 | }; 66 | /** 67 | * Method: remove 68 | * remove an object from this queue if it is owned by this queue and 69 | * return it, or return null if the object is not owned by this queue. 70 | * 71 | * Parameters: 72 | * o - the object to remove 73 | */ 74 | this.remove = function(o) { 75 | if (!o || !o.queue == this) return null; 76 | o.prev.next = o.next; 77 | if (o.next) { 78 | o.next.prev = o.prev; 79 | } 80 | o.queue = null; 81 | return o; 82 | }; 83 | /** 84 | * Method: promote 85 | * promote an object to the top of the queue 86 | * 87 | * Parameters: 88 | * o - the object to promote 89 | */ 90 | this.promote = function(o) { 91 | this.push(this.remove(o)); 92 | }; 93 | }; 94 | 95 | /** 96 | * Method: get 97 | * return an object from the cache and refresh it, or null if not found 98 | * 99 | * Parameters: 100 | * key - the key by which the data is identified 101 | */ 102 | this.get = function(key) { 103 | var o = cache[key], 104 | q, 105 | qn, 106 | popped; 107 | if (o) { 108 | // track the cache hit 109 | o['time'] = Date(); 110 | o.count += 1; 111 | // check the queue based on power of 10 on hit count 112 | qn = Math.ceil(Math.log(o.count)/Math.LN10); 113 | q = queues[qn]; 114 | if (!q) { 115 | var ql = Math.floor(max / Math.pow(2,qn+1)); 116 | if (ql) { 117 | queues[qn] = q = new Queue(ql); 118 | } else { 119 | qn --; 120 | q = queues[qn]; 121 | } 122 | } 123 | if (o.queue != q) { 124 | if (o.queue) { 125 | o.queue.remove(o); 126 | } 127 | q.push(o); 128 | } else { 129 | // promote to top of current queue 130 | q.promote(o); 131 | } 132 | } 133 | return o; 134 | }; 135 | 136 | /** 137 | * Method: set 138 | * put some data in the Cache. If the data is already in the cache, 139 | * update it. 140 | * 141 | * Parameters: 142 | * key - the key by which the data is identified 143 | * data - arbitrary data to store in the cache. 144 | */ 145 | this.set = function(key, data) { 146 | var o = this.get(key), 147 | popped; 148 | if (!o) { 149 | o = { 150 | 'time': Date(), 151 | data: data, 152 | count: 1 153 | }; 154 | cache[key] = o; 155 | // discard things popped from the 0th queue 156 | queues[0].push(o); 157 | } else { 158 | o.data = data; 159 | } 160 | return o; 161 | }; 162 | 163 | /** 164 | * Method: cascade 165 | * cascade an object being displaced from a queue onto another queue, 166 | * recursing to handle an object being displaced as a result of this. 167 | * 168 | * Parameters: 169 | * o - the object being cascaded 170 | * qn - the queue number that the object is being cascaded onto 171 | */ 172 | this.cascade = function(o, qn) { 173 | var q = queues[qn]; 174 | if (o && q) { 175 | o.count = Math.pow(10,qn) - 1; 176 | this.cascade(q.push(o, qn-1)); 177 | } 178 | }; 179 | 180 | var queues = [new Queue(Math.floor(max / 2))]; 181 | 182 | }; 183 | 184 | exports.Cache = Cache; -------------------------------------------------------------------------------- /src/ms_point.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_point.hpp" 2 | 3 | Nan::Persistent MSPoint::constructor; 4 | 5 | void MSPoint::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSPoint::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("Point").ToLocalChecked()); 9 | 10 | RW_ATTR(tpl, "x", PropertyGetter, PropertySetter); 11 | RW_ATTR(tpl, "y", PropertyGetter, PropertySetter); 12 | 13 | Nan::SetPrototypeMethod(tpl, "project", Project); 14 | Nan::SetPrototypeMethod(tpl, "distanceToPoint", DistanceToPoint); 15 | 16 | target->Set(Nan::New("Point").ToLocalChecked(), tpl->GetFunction()); 17 | constructor.Reset(tpl); 18 | } 19 | 20 | MSPoint::MSPoint(pointObj *point) : ObjectWrap(), this_(point) { 21 | owner = false; 22 | } 23 | 24 | MSPoint::MSPoint() : ObjectWrap(), this_(0) { owner = false; } 25 | 26 | MSPoint::~MSPoint() { 27 | if (this_ && owner) { 28 | free(this_); 29 | owner = false; 30 | } 31 | } 32 | 33 | NAN_METHOD(MSPoint::New) { 34 | MSPoint *obj; 35 | 36 | if (!info.IsConstructCall()) { 37 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 38 | } 39 | 40 | if (info[0]->IsExternal()) { 41 | v8::Local ext = info[0].As(); 42 | void* ptr = ext->Value(); 43 | obj = static_cast(ptr); 44 | obj->Wrap(info.This()); 45 | info.GetReturnValue().Set(info.This()); 46 | return; 47 | } 48 | 49 | pointObj *point = (pointObj *)calloc(1, sizeof(pointObj)); 50 | if(!point) { 51 | info.GetReturnValue().Set(info.This()); 52 | return; 53 | } 54 | 55 | double x = -1; 56 | double y = -1; 57 | 58 | 59 | if (info.Length() == 1) { 60 | Nan::ThrowTypeError("Points take numeric 2 arguments, x and y."); 61 | return; 62 | } 63 | 64 | if (info.Length() == 2) { 65 | if (info[0]->IsNumber() && info[1]->IsNumber()) { 66 | x = info[0]->NumberValue(); 67 | y = info[1]->NumberValue(); 68 | } else { 69 | Nan::ThrowTypeError("Points take numeric 2 arguments, x and y."); 70 | return; 71 | } 72 | } 73 | 74 | point->x = x; 75 | point->y = y; 76 | 77 | obj = new MSPoint(point); 78 | obj->owner = true; 79 | obj->Wrap(info.This()); 80 | info.GetReturnValue().Set(info.This()); 81 | } 82 | 83 | v8::Local MSPoint::NewInstance(pointObj *ptr) { 84 | Nan::EscapableHandleScope scope; 85 | MSPoint* obj = new MSPoint(); 86 | obj->this_ = ptr; 87 | v8::Local ext = Nan::New(obj); 88 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 89 | } 90 | 91 | NAN_GETTER(MSPoint::PropertyGetter) { 92 | MSPoint *obj = Nan::ObjectWrap::Unwrap(info.Holder()); 93 | 94 | if (STRCMP(property, "x")) { 95 | info.GetReturnValue().Set(obj->this_->x); 96 | } else if (STRCMP(property, "y")) { 97 | info.GetReturnValue().Set(obj->this_->y); 98 | } 99 | } 100 | 101 | NAN_SETTER(MSPoint::PropertySetter) { 102 | MSPoint *obj = Nan::ObjectWrap::Unwrap(info.Holder()); 103 | if (STRCMP(property, "x")) { 104 | obj->this_->x = value->NumberValue(); 105 | } else if (STRCMP(property, "y")) { 106 | obj->this_->y = value->NumberValue(); 107 | } 108 | } 109 | 110 | NAN_METHOD(MSPoint::Project) { 111 | MSPoint *point = Nan::ObjectWrap::Unwrap(info.Holder()); 112 | 113 | v8::Local obj; 114 | MSProjection *projIn; 115 | MSProjection *projOut; 116 | 117 | if (info.Length() != 2) { 118 | Nan::ThrowError("projecting a point requires two projection arguments"); 119 | return; 120 | } 121 | 122 | if (!info[0]->IsObject()) { 123 | Nan::ThrowTypeError("first argument to project must be Projection object"); 124 | return; 125 | } 126 | 127 | obj = info[0].As(); 128 | 129 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSProjection::constructor)->HasInstance(obj)) { 130 | Nan::ThrowTypeError("first argument to project must be Projection object"); 131 | return; 132 | } 133 | 134 | projIn = Nan::ObjectWrap::Unwrap(obj); 135 | 136 | if (!info[1]->IsObject()) { 137 | Nan::ThrowTypeError("second argument to project must be Projection object"); 138 | return; 139 | } 140 | 141 | obj = info[1].As(); 142 | 143 | 144 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSProjection::constructor)->HasInstance(obj)) { 145 | Nan::ThrowTypeError("second argument to project must be Projection object"); 146 | return; 147 | } 148 | 149 | projOut = Nan::ObjectWrap::Unwrap(obj); 150 | 151 | msProjectPoint(projIn->this_, projOut->this_, point->this_); 152 | } 153 | 154 | NAN_METHOD(MSPoint::DistanceToPoint) { 155 | MSPoint *point = Nan::ObjectWrap::Unwrap(info.Holder()); 156 | 157 | v8::Local obj; 158 | MSPoint *anotherPoint; 159 | 160 | if (info.Length() != 1) { 161 | Nan::ThrowError("distanceToPoint needs a Point to measure to"); 162 | } 163 | 164 | obj = info[0].As(); 165 | 166 | if (!obj->IsObject()) { 167 | Nan::ThrowTypeError("distanceToPoint argument must be Point object"); 168 | } 169 | 170 | 171 | if (obj->IsNull() || obj->IsUndefined() /*|| !Nan::New(MSPoint::constructor)->HasInstance(obj)*/) { 172 | Nan::ThrowTypeError("distanceToPoint argument must be Point object"); 173 | } 174 | 175 | anotherPoint = Nan::ObjectWrap::Unwrap(obj); 176 | 177 | int distance = msDistancePointToPoint(point->this_, anotherPoint->this_); 178 | info.GetReturnValue().Set(distance); 179 | } -------------------------------------------------------------------------------- /src/ms_rect.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_rect.hpp" 2 | 3 | Nan::Persistent MSRect::constructor; 4 | 5 | void MSRect::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSRect::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("Rect").ToLocalChecked()); 9 | 10 | RW_ATTR(tpl, "minx", PropertyGetter, PropertySetter); 11 | RW_ATTR(tpl, "miny", PropertyGetter, PropertySetter); 12 | RW_ATTR(tpl, "maxx", PropertyGetter, PropertySetter); 13 | RW_ATTR(tpl, "maxy", PropertyGetter, PropertySetter); 14 | 15 | Nan::SetPrototypeMethod(tpl, "project", Project); 16 | 17 | target->Set(Nan::New("Rect").ToLocalChecked(), tpl->GetFunction()); 18 | constructor.Reset(tpl); 19 | } 20 | 21 | MSRect::MSRect(rectObj *rect) : ObjectWrap(), this_(rect) { 22 | owner = false; 23 | } 24 | 25 | MSRect::MSRect() : ObjectWrap(), this_(0) { owner = false; } 26 | 27 | MSRect::~MSRect() { 28 | if (this_ && owner) { 29 | free(this_); 30 | owner = false; 31 | } 32 | } 33 | 34 | NAN_METHOD(MSRect::New) { 35 | MSRect *obj; 36 | double t; 37 | 38 | if (!info.IsConstructCall()) { 39 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 40 | return; 41 | } 42 | 43 | if (info[0]->IsExternal()) { 44 | v8::Local ext = info[0].As(); 45 | void* ptr = ext->Value(); 46 | obj = static_cast(ptr); 47 | obj->Wrap(info.This()); 48 | info.GetReturnValue().Set(info.This()); 49 | return; 50 | } 51 | 52 | rectObj *rect = (rectObj *)calloc(1, sizeof(rectObj)); 53 | if(!rect) { 54 | info.GetReturnValue().Set(info.This()); 55 | return; 56 | } 57 | 58 | if (info.Length() == 0) { 59 | rect->minx = -1; 60 | rect->miny = -1; 61 | rect->maxx = -1; 62 | rect->maxy = -1; 63 | } else if (info.Length() == 1) { 64 | 65 | if (!info[0]->IsObject()) { 66 | Nan::ThrowError("single argument constructor requires a Rect object"); 67 | return; 68 | } 69 | 70 | v8::Local obj = info[0].As(); 71 | 72 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSRect::constructor)->HasInstance(obj)) { 73 | Nan::ThrowError("single argument to Rect constructor must be a Rect object"); 74 | return; 75 | } 76 | 77 | MSRect *inRect = Nan::ObjectWrap::Unwrap(obj); 78 | 79 | memcpy(rect, inRect->this_, sizeof(rectObj)); 80 | 81 | } else if (info.Length() == 4) { 82 | 83 | if (!ISNUMERIC(info,0) || !ISNUMERIC(info,1) || !ISNUMERIC(info,2) || !ISNUMERIC(info,3)) { 84 | Nan::ThrowTypeError("Rect constructor requires four numeric values"); 85 | return; 86 | } 87 | double minx = info[0]->NumberValue(); 88 | double miny = info[1]->NumberValue(); 89 | double maxx = info[2]->NumberValue(); 90 | double maxy = info[3]->NumberValue(); 91 | /* coerce correct extent */ 92 | if (minx > maxx) { 93 | t = maxx; 94 | maxx = minx; 95 | minx = t; 96 | } 97 | if (miny > maxy) { 98 | t = maxy; 99 | maxy = miny; 100 | miny = t; 101 | } 102 | rect->minx = minx; 103 | rect->miny = miny; 104 | rect->maxx = maxx; 105 | rect->maxy = maxy; 106 | } else { 107 | Nan::ThrowError("Rect objects take 0, 1 or 4 arguments."); 108 | return; 109 | } 110 | 111 | obj = new MSRect(rect); 112 | obj->owner = true; 113 | obj->Wrap(info.This()); 114 | info.GetReturnValue().Set(info.This()); 115 | } 116 | 117 | v8::Local MSRect::NewInstance(rectObj *ptr) { 118 | Nan::EscapableHandleScope scope; 119 | MSRect* obj = new MSRect(); 120 | obj->this_ = ptr; 121 | v8::Local ext = Nan::New(obj); 122 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 123 | } 124 | 125 | NAN_GETTER(MSRect::PropertyGetter) { 126 | MSRect *rect = Nan::ObjectWrap::Unwrap(info.Holder()); 127 | 128 | if (STRCMP(property, "minx")) { 129 | info.GetReturnValue().Set(rect->this_->minx); 130 | } else if (STRCMP(property, "miny")) { 131 | info.GetReturnValue().Set(rect->this_->miny); 132 | } else if (STRCMP(property, "maxx")) { 133 | info.GetReturnValue().Set(rect->this_->maxx); 134 | } else if (STRCMP(property, "maxy")) { 135 | info.GetReturnValue().Set(rect->this_->maxy); 136 | } 137 | } 138 | 139 | NAN_SETTER(MSRect::PropertySetter) { 140 | MSRect *rect = Nan::ObjectWrap::Unwrap(info.Holder()); 141 | 142 | if (STRCMP(property, "minx")) { 143 | rect->this_->minx = value->NumberValue(); 144 | } else if (STRCMP(property, "miny")) { 145 | rect->this_->miny = value->NumberValue(); 146 | } else if (STRCMP(property, "maxx")) { 147 | rect->this_->maxx = value->NumberValue(); 148 | } else if (STRCMP(property, "maxy")) { 149 | rect->this_->maxy = value->NumberValue(); 150 | } 151 | } 152 | 153 | NAN_METHOD(MSRect::Project) { 154 | MSRect *rect = Nan::ObjectWrap::Unwrap(info.Holder()); 155 | 156 | v8::Local obj; 157 | MSProjection *projIn; 158 | MSProjection *projOut; 159 | 160 | if (info.Length() != 2) { 161 | Nan::ThrowError("projecting a rect requires two projection arguments"); 162 | return; 163 | } 164 | 165 | if (!info[0]->IsObject()) { 166 | Nan::ThrowTypeError("first argument to project must be Projection object"); 167 | return; 168 | } 169 | 170 | obj = info[0].As(); 171 | 172 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSProjection::constructor)->HasInstance(obj)) { 173 | Nan::ThrowTypeError("first argument to project must be Projection object"); 174 | return; 175 | } 176 | 177 | projIn = Nan::ObjectWrap::Unwrap(obj); 178 | 179 | if (!info[1]->IsObject()) { 180 | Nan::ThrowTypeError("second argument to project must be Projection object"); 181 | return; 182 | } 183 | 184 | obj = info[1].As(); 185 | 186 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSProjection::constructor)->HasInstance(obj)) { 187 | Nan::ThrowTypeError("second argument to project must be Projection object"); 188 | return; 189 | } 190 | 191 | projOut = Nan::ObjectWrap::Unwrap(obj); 192 | 193 | msProjectRect(projIn->this_, projOut->this_, rect->this_); 194 | } -------------------------------------------------------------------------------- /tests/data/gmap/etc/COPYRIGHT.TXT: -------------------------------------------------------------------------------- 1 | Bitstream Vera Fonts Copyright 2 | 3 | The fonts have a generous copyright, allowing derivative works (as 4 | long as "Bitstream" or "Vera" are not in the names), and full 5 | redistribution (so long as they are not *sold* by themselves). They 6 | can be be bundled, redistributed and sold with any software. 7 | 8 | The fonts are distributed under the following copyright: 9 | 10 | Copyright 11 | ========= 12 | 13 | Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream 14 | Vera is a trademark of Bitstream, Inc. 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining 17 | a copy of the fonts accompanying this license ("Fonts") and associated 18 | documentation files (the "Font Software"), to reproduce and distribute 19 | the Font Software, including without limitation the rights to use, 20 | copy, merge, publish, distribute, and/or sell copies of the Font 21 | Software, and to permit persons to whom the Font Software is furnished 22 | to do so, subject to the following conditions: 23 | 24 | The above copyright and trademark notices and this permission notice 25 | shall be included in all copies of one or more of the Font Software 26 | typefaces. 27 | 28 | The Font Software may be modified, altered, or added to, and in 29 | particular the designs of glyphs or characters in the Fonts may be 30 | modified and additional glyphs or characters may be added to the 31 | Fonts, only if the fonts are renamed to names not containing either 32 | the words "Bitstream" or the word "Vera". 33 | 34 | This License becomes null and void to the extent applicable to Fonts 35 | or Font Software that has been modified and is distributed under the 36 | "Bitstream Vera" names. 37 | 38 | The Font Software may be sold as part of a larger software package but 39 | no copy of one or more of the Font Software typefaces may be sold by 40 | itself. 41 | 42 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 43 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 44 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 45 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL 46 | BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR 47 | OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, 48 | OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR 49 | OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT 50 | SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 51 | 52 | Except as contained in this notice, the names of Gnome, the Gnome 53 | Foundation, and Bitstream Inc., shall not be used in advertising or 54 | otherwise to promote the sale, use or other dealings in this Font 55 | Software without prior written authorization from the Gnome Foundation 56 | or Bitstream Inc., respectively. For further information, contact: 57 | fonts at gnome dot org. 58 | 59 | Copyright FAQ 60 | ============= 61 | 62 | 1. I don't understand the resale restriction... What gives? 63 | 64 | Bitstream is giving away these fonts, but wishes to ensure its 65 | competitors can't just drop the fonts as is into a font sale system 66 | and sell them as is. It seems fair that if Bitstream can't make money 67 | from the Bitstream Vera fonts, their competitors should not be able to 68 | do so either. You can sell the fonts as part of any software package, 69 | however. 70 | 71 | 2. I want to package these fonts separately for distribution and 72 | sale as part of a larger software package or system. Can I do so? 73 | 74 | Yes. A RPM or Debian package is a "larger software package" to begin 75 | with, and you aren't selling them independently by themselves. 76 | See 1. above. 77 | 78 | 3. Are derivative works allowed? 79 | Yes! 80 | 81 | 4. Can I change or add to the font(s)? 82 | Yes, but you must change the name(s) of the font(s). 83 | 84 | 5. Under what terms are derivative works allowed? 85 | 86 | You must change the name(s) of the fonts. This is to ensure the 87 | quality of the fonts, both to protect Bitstream and Gnome. We want to 88 | ensure that if an application has opened a font specifically of these 89 | names, it gets what it expects (though of course, using fontconfig, 90 | substitutions could still could have occurred during font 91 | opening). You must include the Bitstream copyright. Additional 92 | copyrights can be added, as per copyright law. Happy Font Hacking! 93 | 94 | 6. If I have improvements for Bitstream Vera, is it possible they might get 95 | adopted in future versions? 96 | 97 | Yes. The contract between the Gnome Foundation and Bitstream has 98 | provisions for working with Bitstream to ensure quality additions to 99 | the Bitstream Vera font family. Please contact us if you have such 100 | additions. Note, that in general, we will want such additions for the 101 | entire family, not just a single font, and that you'll have to keep 102 | both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add 103 | glyphs to the font, they must be stylistically in keeping with Vera's 104 | design. Vera cannot become a "ransom note" font. Jim Lyles will be 105 | providing a document describing the design elements used in Vera, as a 106 | guide and aid for people interested in contributing to Vera. 107 | 108 | 7. I want to sell a software package that uses these fonts: Can I do so? 109 | 110 | Sure. Bundle the fonts with your software and sell your software 111 | with the fonts. That is the intent of the copyright. 112 | 113 | 8. If applications have built the names "Bitstream Vera" into them, 114 | can I override this somehow to use fonts of my choosing? 115 | 116 | This depends on exact details of the software. Most open source 117 | systems and software (e.g., Gnome, KDE, etc.) are now converting to 118 | use fontconfig (see www.fontconfig.org) to handle font configuration, 119 | selection and substitution; it has provisions for overriding font 120 | names and subsituting alternatives. An example is provided by the 121 | supplied local.conf file, which chooses the family Bitstream Vera for 122 | "sans", "serif" and "monospace". Other software (e.g., the XFree86 123 | core server) has other mechanisms for font substitution. 124 | 125 | -------------------------------------------------------------------------------- /tests/data/gmap/htdocs/gmap75.map: -------------------------------------------------------------------------------- 1 | # 2 | # Start of GMAP map file 3 | # 4 | # 5 | MAP 6 | NAME GMAP_DEMO 7 | STATUS ON 8 | #SIZE 400 300 9 | SIZE 612 792 10 | SYMBOLSET ../etc/symbols.sym 11 | EXTENT -2200000 -712631 3072800 3840000 12 | UNITS METERS 13 | SHAPEPATH "../data" 14 | IMAGECOLOR 255 255 255 15 | FONTSET ../etc/fonts.txt 16 | 17 | 18 | projection 19 | "init=epsg:42304" 20 | end 21 | # 22 | # Start of web interface definition 23 | # 24 | WEB 25 | MINSCALE 2000000 26 | MAXSCALE 50000000 27 | # 28 | # On Windows systems, /tmp and /tmp/ms_tmp/ should be created at the root 29 | # of the drive where the .MAP file resides. 30 | # 31 | IMAGEPATH "/opt/fgs-dev/tmp/ms_tmp/" 32 | IMAGEURL "/ms_tmp/" 33 | METADATA 34 | "legend_title" "GMAP Viewer test map" 35 | "map_title" "Map Title goes here test" 36 | "map_abstract" "Short description of a map goes here" 37 | "map_description" "" 38 | "map_copyright" "© copyright for this map 2010" 39 | "map_hyperlink" "www_common/info.html" 40 | END 41 | END 42 | 43 | # 44 | # Start of reference map 45 | # 46 | REFERENCE 47 | IMAGE images/keymap.png 48 | EXTENT -2200000 -712631 3072800 3840000 49 | STATUS ON 50 | COLOR -1 -1 -1 51 | OUTLINECOLOR 255 0 0 52 | SIZE 120 90 53 | END 54 | 55 | # 56 | # Start of legend 57 | # 58 | LEGEND 59 | KEYSIZE 16 16 60 | LABEL 61 | TYPE BITMAP 62 | SIZE MEDIUM 63 | COLOR 0 0 89 64 | END 65 | STATUS ON 66 | END 67 | 68 | # 69 | # Start of scalebar 70 | # 71 | SCALEBAR 72 | IMAGECOLOR 255 255 255 73 | LABEL 74 | COLOR 0 0 0 75 | SIZE SMALL 76 | END 77 | SIZE 150 5 78 | COLOR 255 255 255 79 | BACKGROUNDCOLOR 0 0 0 80 | OUTLINECOLOR 0 0 0 81 | UNITS kilometers 82 | INTERVALS 5 83 | STATUS ON 84 | END 85 | 86 | 87 | QUERYMAP 88 | STYLE HILITE 89 | COLOR 255 0 0 90 | END 91 | 92 | 93 | # 94 | # Start of layer definitions 95 | # 96 | 97 | 98 | LAYER 99 | NAME bathymetry 100 | GROUP "Waterbodies" 101 | METADATA 102 | "DESCRIPTION" "Elevation/Bathymetry" 103 | END 104 | TYPE RASTER 105 | STATUS ON 106 | DATA bath_mapserver.tif 107 | END 108 | 109 | LAYER 110 | NAME land_fn 111 | METADATA 112 | "DESCRIPTION" "Foreign Lands" 113 | "LEGENDLABEL" "Foreign Lands" 114 | "LAYERINFOURL" "http://google.com/" 115 | "layer_description" "path/to/layer/description.html" 116 | END 117 | TYPE POLYGON 118 | STATUS ON 119 | DATA land_fn 120 | CLASS 121 | NAME "Foreign Lands" 122 | STYLE 123 | COLOR 240 240 240 124 | OUTLINECOLOR 199 199 199 125 | END 126 | END 127 | END # layer 128 | 129 | LAYER 130 | NAME park 131 | METADATA 132 | "DESCRIPTION" "Parks" 133 | "RESULT_FIELDS" "NAME_E YEAR_EST AREA_KMSQ" 134 | "selectable" "true" 135 | "LAYERINFOURL" "http://google.com/" 136 | END 137 | TYPE POLYGON 138 | STATUS OFF 139 | DATA park 140 | CLASS 141 | NAME "Parks" 142 | STYLE 143 | COLOR 200 255 0 144 | OUTLINECOLOR 120 120 120 145 | END 146 | TEMPLATE "ttt_query.html" 147 | END 148 | TOLERANCE 5 149 | END # Layer 150 | 151 | LAYER 152 | NAME drain_fn 153 | GROUP "Waterbodies" 154 | METADATA 155 | "DESCRIPTION" "Foreign Water" 156 | "LAYERINFOURL" "http://google.com/" 157 | END 158 | TYPE POLYGON 159 | STATUS ON 160 | DATA drain_fn 161 | CLASSITEM "Poly_featu" 162 | CLASS 163 | EXPRESSION /16|21/ 164 | NAME "Water" 165 | STYLE 166 | COLOR 225 249 255 167 | OUTLINECOLOR 186 234 245 168 | END 169 | END 170 | END # layer 171 | 172 | LAYER 173 | NAME drainage 174 | GROUP "Waterbodies" 175 | METADATA 176 | "DESCRIPTION" "Drainage" 177 | "LAYERINFOURL" "http://google.com/" 178 | END 179 | TYPE POLYGON 180 | STATUS ON 181 | DATA drainage 182 | CLASSITEM "Poly_featu" 183 | CLASS 184 | EXPRESSION "0" 185 | NAME "Water" 186 | STYLE 187 | COLOR 225 249 255 188 | OUTLINECOLOR 186 234 245 189 | END 190 | END 191 | END # layer 192 | 193 | LAYER 194 | NAME prov_bound 195 | METADATA 196 | "DESCRIPTION" "Province" 197 | END 198 | TYPE LINE 199 | STATUS ON 200 | DATA province 201 | CLASS 202 | NAME "Province" 203 | STYLE 204 | COLOR 120 120 120 205 | END 206 | END 207 | END # layer 208 | 209 | LAYER 210 | NAME fedlimit 211 | METADATA 212 | "DESCRIPTION" "Federal Limit" 213 | END 214 | TYPE LINE 215 | STATUS ON 216 | DATA fedlimit 217 | CLASS 218 | NAME "Federal Limit" 219 | STYLE 220 | SYMBOL 3 221 | COLOR 0 119 255 222 | END 223 | END 224 | 225 | END # Layer 226 | 227 | LAYER 228 | NAME rail 229 | METADATA 230 | "DESCRIPTION" "Railroads" 231 | END 232 | TYPE LINE 233 | STATUS OFF 234 | DATA rail 235 | CLASS 236 | NAME "Railroads" 237 | STYLE 238 | SYMBOL 0 239 | COLOR 168 0 184 240 | END 241 | END 242 | END # Layer 243 | 244 | LAYER 245 | NAME road 246 | METADATA 247 | "DESCRIPTION" "Roads" 248 | END 249 | TYPE LINE 250 | STATUS OFF 251 | DATA road 252 | CLASS 253 | NAME "Roads" 254 | STYLE 255 | SYMBOL 0 256 | COLOR 220 0 0 257 | END 258 | END 259 | END # Layer 260 | 261 | LAYER 262 | NAME popplace 263 | METADATA 264 | "DESCRIPTION" "Cities" 265 | "RESULT_FIELDS" "NAME" 266 | "selectable" "true" 267 | END 268 | TYPE POINT 269 | STATUS ON 270 | DATA popplace 271 | LabelItem "Name" 272 | CLASSITEM "Capital" 273 | CLASS 274 | EXPRESSION "1" 275 | TEMPLATE "ttt_query.html" 276 | NAME "Cities" 277 | LABEL 278 | COLOR 255 0 0 279 | FONT sans-italic 280 | TYPE truetype 281 | SIZE 8 282 | POSITION AUTO 283 | PARTIALS FALSE 284 | OUTLINECOLOR 255 255 255 285 | END 286 | STYLE 287 | SYMBOL 2 288 | SIZE 8 289 | COLOR 0 0 0 290 | END 291 | END 292 | CLASS 293 | EXPRESSION /2|3/ 294 | TEMPLATE "ttt_query.html" 295 | NAME "Cities" 296 | LABEL 297 | COLOR 0 0 0 298 | FONT sans 299 | TYPE truetype 300 | SIZE 8 301 | POSITION AUTO 302 | PARTIALS FALSE 303 | OUTLINECOLOR 255 255 255 304 | END 305 | STYLE 306 | SYMBOL 7 307 | SIZE 6 308 | COLOR 0 0 0 309 | END 310 | END 311 | TOLERANCE 5 312 | END # Layer 313 | 314 | LAYER 315 | NAME "grid" 316 | METADATA 317 | "DESCRIPTION" "Grid" 318 | END 319 | TYPE LINE 320 | STATUS OFF 321 | DATA "grid" 322 | CLASS 323 | NAME "Graticule" 324 | STYLE 325 | COLOR 0 0 0 326 | END 327 | END 328 | END # Layer 329 | 330 | 331 | END # Map File 332 | -------------------------------------------------------------------------------- /tests/data/gmap/htdocs/gmap75_wms.map: -------------------------------------------------------------------------------- 1 | # 2 | # Start of WMS Server map file 3 | # 4 | # 5 | NAME WMS_server 6 | STATUS ON 7 | SIZE 400 300 8 | SYMBOLSET ../etc/symbols.sym 9 | ## ESPG:42304 extents: 10 | EXTENT -2200000 -712631 3072800 3840000 11 | UNITS METERS 12 | SHAPEPATH "../data" 13 | IMAGECOLOR 255 255 255 14 | FONTSET ../etc/fonts.txt 15 | 16 | 17 | # 18 | # Start of web interface definition 19 | # 20 | WEB 21 | # 22 | # On Windows systems, /tmp and /tmp/ms_tmp/ should be created at the root 23 | # of the drive where the .MAP file resides. 24 | # 25 | IMAGEPATH "/ms4w/tmp/ms_tmp/" 26 | IMAGEURL "/ms_tmp/" 27 | METADATA 28 | "wms_title" "GMap WMS Demo Server" 29 | "wms_onlineresource" "http://127.0.0.1/cgi-bin/mapserv.exe?MAP=/ms4w/apps/gmap/htdocs/gmap75_wms.map" 30 | "wms_srs" "EPSG:42304 EPSG:42101 EPSG:4269 EPSG:4326" 31 | "wms_feature_info_mime_type" "text/html" 32 | "wms_abstract" "This demonstration server was setup by DM Solutions Group (http://www.dmsolutions.ca/) and is powered by the UMN MapServer (http://mapserver.gis.umn.edu/). This server uses Canadian source data (c)2000, Government of Canada with permission from Natural Resources Canada from NRCan's GeoGratis 33 | web site (http://geogratis.cgdi.gc.ca/)." 34 | END 35 | END 36 | 37 | PROJECTION 38 | "init=epsg:42304" 39 | END 40 | 41 | # 42 | # Start of reference map 43 | # 44 | REFERENCE 45 | IMAGE images/keymap.png 46 | #EPSG:42304 extents 47 | EXTENT -2200000 -712631 3072800 3840000 48 | STATUS ON 49 | COLOR -1 -1 -1 50 | OUTLINECOLOR 255 0 0 51 | SIZE 120 90 52 | END 53 | 54 | # 55 | # Start of legend 56 | # 57 | LEGEND 58 | KEYSIZE 18 12 59 | LABEL 60 | TYPE BITMAP 61 | SIZE MEDIUM 62 | COLOR 0 0 89 63 | END 64 | STATUS ON 65 | END 66 | 67 | # 68 | # Start of scalebar 69 | # 70 | SCALEBAR 71 | IMAGECOLOR 255 255 255 72 | LABEL 73 | COLOR 0 0 0 74 | SIZE SMALL 75 | END 76 | SIZE 200 5 77 | COLOR 255 255 255 78 | BACKGROUNDCOLOR 0 0 0 79 | OUTLINECOLOR 0 0 0 80 | UNITS kilometers 81 | INTERVALS 5 82 | STATUS ON 83 | END 84 | 85 | 86 | QUERYMAP 87 | STYLE HILITE 88 | COLOR 255 0 0 89 | END 90 | 91 | 92 | # 93 | # Start of layer definitions 94 | # 95 | 96 | 97 | LAYER 98 | NAME bathymetry 99 | METADATA 100 | "wms_title" "Elevation/Bathymetry" 101 | END 102 | TYPE RASTER 103 | STATUS ON 104 | DATA bath_mapserver.tif 105 | PROJECTION 106 | "init=epsg:42304" 107 | END 108 | END 109 | 110 | 111 | LAYER 112 | NAME land_fn 113 | METADATA 114 | "wms_title" "Foreign Lands" 115 | END 116 | TYPE POLYGON 117 | STATUS OFF 118 | DATA land_fn 119 | PROJECTION 120 | "init=epsg:42304" 121 | END 122 | CLASS 123 | NAME "Foreign Lands" 124 | STYLE 125 | COLOR 240 240 240 126 | OUTLINECOLOR 199 199 199 127 | END 128 | END 129 | END # layer 130 | 131 | LAYER 132 | NAME park 133 | METADATA 134 | "wms_title" "Parks" 135 | END 136 | TYPE POLYGON 137 | STATUS OFF 138 | DATA park 139 | PROJECTION 140 | "init=epsg:42304" 141 | END 142 | CLASS 143 | NAME "Parks" 144 | STYLE 145 | COLOR 200 255 0 146 | OUTLINECOLOR 120 120 120 147 | END 148 | END 149 | END # Layer 150 | 151 | LAYER 152 | NAME drain_fn 153 | METADATA 154 | "wms_title" "Water" 155 | END 156 | TYPE POLYGON 157 | STATUS ON 158 | DATA drain_fn 159 | PROJECTION 160 | "init=epsg:42304" 161 | END 162 | CLASSITEM "Poly_featu" 163 | CLASS 164 | EXPRESSION /16|21/ 165 | NAME "Water" 166 | STYLE 167 | COLOR 225 249 255 168 | OUTLINECOLOR 186 234 245 169 | END 170 | END 171 | END # layer 172 | 173 | LAYER 174 | NAME drainage 175 | METADATA 176 | "wms_title" "Drainage" 177 | END 178 | TYPE POLYGON 179 | STATUS ON 180 | DATA drainage 181 | PROJECTION 182 | "init=epsg:42304" 183 | END 184 | CLASSITEM "Poly_featu" 185 | CLASS 186 | EXPRESSION "0" 187 | NAME "Water" 188 | STYLE 189 | COLOR 225 249 255 190 | OUTLINECOLOR 186 234 245 191 | END 192 | END 193 | END # layer 194 | 195 | LAYER 196 | NAME prov_bound 197 | METADATA 198 | "wms_title" "Province" 199 | END 200 | TYPE LINE 201 | STATUS ON 202 | DATA province 203 | PROJECTION 204 | "init=epsg:42304" 205 | END 206 | CLASS 207 | NAME "Province" 208 | STYLE 209 | COLOR 120 120 120 210 | END 211 | END 212 | END # layer 213 | 214 | LAYER 215 | NAME fedlimit 216 | METADATA 217 | "wms_title" "Federal Limit" 218 | END 219 | TYPE LINE 220 | STATUS ON 221 | DATA fedlimit 222 | PROJECTION 223 | "init=epsg:42304" 224 | END 225 | CLASS 226 | NAME "Federal Limit" 227 | STYLE 228 | SYMBOL 3 229 | COLOR 0 119 255 230 | END 231 | END 232 | END # Layer 233 | 234 | LAYER 235 | NAME rail 236 | METADATA 237 | "wms_title" "Railroads" 238 | END 239 | TYPE LINE 240 | STATUS OFF 241 | DATA rail 242 | PROJECTION 243 | "init=epsg:42304" 244 | END 245 | CLASS 246 | NAME "Railroads" 247 | STYLE 248 | SYMBOL 0 249 | COLOR 168 0 184 250 | END 251 | END 252 | END # Layer 253 | 254 | LAYER 255 | NAME road 256 | METADATA 257 | "wms_title" "Roads" 258 | END 259 | TYPE LINE 260 | STATUS OFF 261 | DATA road 262 | PROJECTION 263 | "init=epsg:42304" 264 | END 265 | CLASS 266 | NAME "Roads" 267 | STYLE 268 | SYMBOL 0 269 | COLOR 220 0 0 270 | END 271 | END 272 | END # Layer 273 | 274 | LAYER 275 | NAME popplace 276 | METADATA 277 | "wms_title" "Cities" 278 | END 279 | TYPE POINT 280 | STATUS ON 281 | DATA popplace 282 | PROJECTION 283 | "init=epsg:42304" 284 | END 285 | LabelItem "Name" 286 | CLASSITEM "Capital" 287 | CLASS 288 | EXPRESSION "1" 289 | NAME "Cities" 290 | LABEL 291 | COLOR 255 0 0 292 | FONT sans-italic 293 | TYPE truetype 294 | SIZE 8 295 | POSITION AUTO 296 | PARTIALS FALSE 297 | OUTLINECOLOR 255 255 255 298 | END 299 | STYLE 300 | SYMBOL 2 301 | SIZE 8 302 | COLOR 0 0 0 303 | END 304 | END 305 | CLASS 306 | EXPRESSION /2|3/ 307 | NAME "Cities" 308 | LABEL 309 | COLOR 0 0 0 310 | FONT sans 311 | TYPE truetype 312 | SIZE 8 313 | POSITION AUTO 314 | PARTIALS FALSE 315 | OUTLINECOLOR 255 255 255 316 | END 317 | STYLE 318 | SYMBOL 7 319 | SIZE 6 320 | COLOR 0 0 0 321 | END 322 | END 323 | END # Layer 324 | 325 | LAYER 326 | NAME "grid" 327 | METADATA 328 | "wms_title" "Grid" 329 | END 330 | TYPE LINE 331 | STATUS OFF 332 | DATA "grid" 333 | PROJECTION 334 | "init=epsg:42304" 335 | END 336 | CLASS 337 | NAME "Graticule" 338 | STYLE 339 | COLOR 0 0 0 340 | END 341 | END 342 | END # Layer 343 | 344 | 345 | END # Map File 346 | -------------------------------------------------------------------------------- /tests/data/gmap/htdocs/gmap75_platform.map: -------------------------------------------------------------------------------- 1 | MAP 2 | NAME "GMAP_DEMO" 3 | STATUS ON 4 | SYMBOLSET "../etc/symbols.txt" 5 | EXTENT -2200000 -712631 3072800 3840000 6 | UNITS METERS 7 | SHAPEPATH "../data" 8 | IMAGECOLOR 255 255 255 9 | FONTSET "../etc/fonts.txt" 10 | SIZE 612 792 11 | IMAGETYPE "aggpng24" 12 | 13 | OUTPUTFORMAT 14 | NAME "aggpng24" 15 | DRIVER AGG/PNG 16 | MIMETYPE "image/png" 17 | IMAGEMODE RGB 18 | EXTENSION "png" 19 | END 20 | 21 | PROJECTION 22 | "init=epsg:42304" 23 | END 24 | 25 | WEB 26 | MINSCALEDENOM 2000000 27 | MAXSCALEDENOM 50000000 28 | IMAGEPATH "/opt/fgs-dev/tmp/ms_tmp/" 29 | IMAGEURL "/ms_tmp/" 30 | METADATA 31 | "legend_title" "GMAP Viewer test map" 32 | "map_title" "Map Title goes here test" 33 | "map_abstract" "Short description of a map goes here" 34 | "map_description" "www_common/info.html" 35 | "map_copyright" "© copyright for this map 2010" 36 | "map_hyperlink" "http://openlayers.org/" 37 | END 38 | END 39 | 40 | LEGEND 41 | KEYSIZE 16 16 42 | END 43 | 44 | QUERYMAP 45 | STYLE HILITE 46 | COLOR 255 0 0 47 | END 48 | 49 | LAYER 50 | NAME "bathymetry" 51 | GROUP "Waterbodies" 52 | METADATA 53 | "LEGENDLABEL" "Elevation and Bathymetry" 54 | "LAYERINFOURL" "" 55 | "layer_description" "" 56 | END 57 | TYPE RASTER 58 | STATUS ON 59 | DATA "bath_mapserver.tif" 60 | END 61 | 62 | LAYER 63 | NAME "land_fn" 64 | METADATA 65 | "LEGENDLABEL" "Foreign Lands" 66 | "LAYERINFOURL" "http://google.com/" 67 | "layer_description" "path/to/layer/description.html" 68 | END 69 | TYPE POLYGON 70 | STATUS ON 71 | DATA "land_fn" 72 | CLASS 73 | NAME "Foreign Lands" 74 | STYLE 75 | COLOR 240 240 240 76 | OUTLINECOLOR 199 199 199 77 | END 78 | END 79 | END # layer 80 | 81 | LAYER 82 | NAME "park" 83 | METADATA 84 | "LEGENDLABEL" "Parks" 85 | "RESULT_FIELDS" "NAME_E YEAR_EST AREA_KMSQ" 86 | "selectable" "true" 87 | "LAYERINFOURL" "" 88 | "layer_description" "" 89 | END 90 | TYPE POLYGON 91 | STATUS OFF 92 | DATA "park" 93 | CLASS 94 | NAME "Parks" 95 | TEMPLATE "ttt_query.html" 96 | STYLE 97 | COLOR 200 255 0 98 | OUTLINECOLOR 120 120 120 99 | END 100 | END 101 | TOLERANCE 5 102 | END # Layer 103 | 104 | LAYER 105 | NAME "drain_fn" 106 | GROUP "Waterbodies" 107 | METADATA 108 | "LEGENDLABEL" "Foreign Water" 109 | "LAYERINFOURL" "" 110 | "layer_description" "" 111 | END 112 | TYPE POLYGON 113 | STATUS ON 114 | DATA "drain_fn" 115 | CLASSITEM "Poly_featu" 116 | CLASS 117 | EXPRESSION /16|21/ 118 | NAME "Water" 119 | STYLE 120 | COLOR 225 249 255 121 | OUTLINECOLOR 186 234 245 122 | END 123 | END 124 | END # layer 125 | 126 | LAYER 127 | NAME "drainage" 128 | GROUP "Waterbodies" 129 | METADATA 130 | "LEGENDLABEL" "Drainage" 131 | "LAYERINFOURL" "" 132 | "layer_description" "" 133 | END 134 | TYPE POLYGON 135 | STATUS ON 136 | DATA "drainage" 137 | CLASSITEM "Poly_featu" 138 | CLASS 139 | EXPRESSION "0" 140 | NAME "Water" 141 | STYLE 142 | COLOR 225 249 255 143 | OUTLINECOLOR 186 234 245 144 | END 145 | END 146 | END # layer 147 | 148 | LAYER 149 | NAME "prov_bound" 150 | METADATA 151 | "LEGENDLABEL" "Provinces" 152 | "LAYERINFOURL" "" 153 | "layer_description" "" 154 | END 155 | TYPE LINE 156 | STATUS ON 157 | DATA "province" 158 | CLASS 159 | NAME "Province" 160 | STYLE 161 | WIDTH 1 162 | COLOR 120 120 120 163 | END 164 | END 165 | END # layer 166 | 167 | LAYER 168 | NAME "fedlimit" 169 | METADATA 170 | "LEGENDLABEL" "Federal Limit" 171 | "LAYERINFOURL" "" 172 | "layer_description" "" 173 | END 174 | TYPE LINE 175 | STATUS ON 176 | DATA "fedlimit" 177 | CLASS 178 | NAME "Federal Limit" 179 | STYLE 180 | WIDTH 1 181 | COLOR 0 119 255 182 | END 183 | END 184 | END # Layer 185 | 186 | LAYER 187 | NAME "rail" 188 | METADATA 189 | "LEGENDLABEL" "Railroads" 190 | "LAYERINFOURL" "" 191 | "layer_description" "" 192 | END 193 | TYPE LINE 194 | STATUS OFF 195 | DATA "rail" 196 | CLASS 197 | NAME "Railroads" 198 | STYLE 199 | WIDTH 1 200 | COLOR 168 0 184 201 | END 202 | END 203 | END # Layer 204 | 205 | LAYER 206 | NAME road 207 | METADATA 208 | "LEGENDLABEL" "Roads" 209 | "LAYERINFOURL" "" 210 | "layer_description" "" 211 | END 212 | TYPE LINE 213 | STATUS OFF 214 | DATA road 215 | CLASS 216 | NAME "Roads" 217 | STYLE 218 | WIDTH 1 219 | COLOR 220 0 0 220 | END 221 | END 222 | END # Layer 223 | 224 | LAYER 225 | NAME popplace 226 | METADATA 227 | "LEGENDLABEL" "Cities" 228 | "RESULT_FIELDS" "NAME" 229 | "selectable" "true" 230 | "LAYERINFOURL" "" 231 | "layer_description" "" 232 | END 233 | TYPE POINT 234 | STATUS ON 235 | DATA popplace 236 | LabelItem "Name" 237 | CLASSITEM "Capital" 238 | CLASS 239 | EXPRESSION "1" 240 | TEMPLATE "ttt_query.html" 241 | NAME "Cities" 242 | LABEL 243 | COLOR 255 0 0 244 | FONT sans-italic 245 | TYPE truetype 246 | SIZE 8 247 | POSITION AUTO 248 | PARTIALS FALSE 249 | OUTLINECOLOR 255 255 255 250 | END 251 | STYLE 252 | SYMBOL "star" 253 | SIZE 8 254 | COLOR 0 0 0 255 | END 256 | END 257 | CLASS 258 | EXPRESSION /2|3/ 259 | TEMPLATE "ttt_query.html" 260 | NAME "Cities" 261 | LABEL 262 | COLOR 0 0 0 263 | FONT sans 264 | TYPE truetype 265 | SIZE 8 266 | POSITION AUTO 267 | PARTIALS FALSE 268 | OUTLINECOLOR 255 255 255 269 | END 270 | STYLE 271 | SYMBOL "circle" 272 | SIZE 6 273 | COLOR 0 0 0 274 | END 275 | END 276 | TOLERANCE 5 277 | END # Layer 278 | 279 | LAYER 280 | NAME "grid" 281 | METADATA 282 | "LEGENDLABEL" "Graticule" 283 | "LAYERINFOURL" "" 284 | "layer_description" "" 285 | END 286 | TYPE LINE 287 | STATUS OFF 288 | DATA "grid" 289 | CLASS 290 | NAME "Graticule" 291 | STYLE 292 | WIDTH 1 293 | COLOR 0 0 0 294 | END 295 | END 296 | END # Layer 297 | 298 | END # Map File 299 | -------------------------------------------------------------------------------- /src/ms_layer.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_layer.hpp" 2 | #include "ms_hashtable.hpp" 3 | #include "ms_projection.hpp" 4 | 5 | Nan::Persistent MSLayer::constructor; 6 | 7 | void MSLayer::Initialize(v8::Local target) { 8 | v8::Local tpl = Nan::New (MSLayer::New); 9 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 10 | tpl->SetClassName(Nan::New("Layer").ToLocalChecked()); 11 | 12 | Nan::SetPrototypeMethod(tpl, "getGridIntersectionCoordinates", GetGridIntersectionCoordinates); 13 | Nan::SetPrototypeMethod(tpl, "updateFromString", UpdateFromString); 14 | #if MS_VERSION_NUM >= 60400 15 | Nan::SetPrototypeMethod(tpl, "toString", ToString); 16 | #endif 17 | 18 | RW_ATTR(tpl, "name", PropertyGetter, PropertySetter); 19 | RW_ATTR(tpl, "status", PropertyGetter, PropertySetter); 20 | RW_ATTR(tpl, "type", PropertyGetter, PropertySetter); 21 | RW_ATTR(tpl, "connection", PropertyGetter, PropertySetter); 22 | RW_ATTR(tpl, "minscaledenom", PropertyGetter, PropertySetter); 23 | RW_ATTR(tpl, "maxscaledenom", PropertyGetter, PropertySetter); 24 | RW_ATTR(tpl, "projection", PropertyGetter, PropertySetter); 25 | RW_ATTR(tpl, "units", PropertyGetter, PropertySetter); 26 | RO_ATTR(tpl, "connectiontype", PropertyGetter); 27 | RO_ATTR(tpl, "metadata", PropertyGetter); 28 | 29 | target->Set(Nan::New("Layer").ToLocalChecked(), tpl->GetFunction()); 30 | constructor.Reset(tpl); 31 | } 32 | 33 | MSLayer::MSLayer(layerObj *layer) : ObjectWrap(), this_(layer) {} 34 | 35 | MSLayer::MSLayer() : ObjectWrap(), this_(0) {} 36 | 37 | MSLayer::~MSLayer() { } 38 | 39 | NAN_METHOD(MSLayer::New) 40 | { 41 | MSLayer* obj; 42 | if (!info.IsConstructCall()) { 43 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 44 | return; 45 | } 46 | 47 | if (info[0]->IsExternal()) { 48 | v8::Local ext = info[0].As(); 49 | void *ptr = ext->Value(); 50 | MSLayer *f = static_cast(ptr); 51 | f->Wrap(info.This()); 52 | info.GetReturnValue().Set(info.This()); 53 | return; 54 | } 55 | 56 | if (info.Length() != 1 || !info[0]->IsString()) { 57 | Nan::ThrowTypeError("requires one argument: a string"); 58 | return; 59 | } 60 | 61 | layerObj* layer = (layerObj*)calloc(1,sizeof(layerObj)); 62 | initLayer(layer, (mapObj*)NULL); 63 | 64 | layer->name = strdup(TOSTR(info[0])); 65 | 66 | obj = new MSLayer(layer); 67 | obj->Wrap(info.This()); 68 | info.GetReturnValue().Set(info.This()); 69 | } 70 | 71 | v8::Local MSLayer::NewInstance(layerObj *ptr) { 72 | Nan::EscapableHandleScope scope; 73 | MSLayer* obj = new MSLayer(); 74 | obj->this_ = ptr; 75 | v8::Local ext = Nan::New(obj); 76 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 77 | } 78 | 79 | NAN_GETTER(MSLayer::PropertyGetter) { 80 | 81 | MSLayer *obj = Nan::ObjectWrap::Unwrap(info.Holder()); 82 | 83 | if (STRCMP(property, "name")) { 84 | info.GetReturnValue().Set(Nan::New(obj->this_->name).ToLocalChecked()); 85 | } else if (STRCMP(property, "status")) { 86 | info.GetReturnValue().Set(obj->this_->status); 87 | } else if (STRCMP(property, "metadata")) { 88 | info.GetReturnValue().Set(MSHashTable::NewInstance(&(obj->this_->metadata))); 89 | } else if (STRCMP(property, "type")) { 90 | info.GetReturnValue().Set(obj->this_->type); 91 | } else if (STRCMP(property, "minscaledenom")) { 92 | info.GetReturnValue().Set(obj->this_->minscaledenom); 93 | } else if (STRCMP(property, "maxscaledenom")) { 94 | info.GetReturnValue().Set(obj->this_->maxscaledenom); 95 | } else if (STRCMP(property, "units")) { 96 | info.GetReturnValue().Set(obj->this_->units); 97 | } else if (STRCMP(property, "projection")) { 98 | info.GetReturnValue().Set(MSProjection::NewInstance(&obj->this_->projection)); 99 | } else if (STRCMP(property, "connection")) { 100 | if (obj->this_->connection == NULL) { 101 | info.GetReturnValue().Set(Nan::Undefined()); 102 | } else { 103 | info.GetReturnValue().Set(Nan::New(obj->this_->connection).ToLocalChecked()); 104 | } 105 | } else if (STRCMP(property, "connectiontype")) { 106 | info.GetReturnValue().Set(obj->this_->connectiontype); 107 | } 108 | } 109 | 110 | NAN_SETTER(MSLayer::PropertySetter) { 111 | MSLayer *obj = Nan::ObjectWrap::Unwrap(info.Holder()); 112 | 113 | if (STRCMP(property, "name")) { 114 | REPLACE_STRING(obj->this_->name, value) 115 | } else if (STRCMP(property, "status")) { 116 | obj->this_->status = value->NumberValue(); 117 | } else if (STRCMP(property, "minscaledenom")) { 118 | obj->this_->minscaledenom = value->NumberValue(); 119 | } else if (STRCMP(property, "maxscaledenom")) { 120 | obj->this_->maxscaledenom = value->NumberValue(); 121 | } else if (STRCMP(property, "units")) { 122 | int32_t units = value->Int32Value(); 123 | if (units >= MS_INCHES && units <= MS_NAUTICALMILES) { 124 | obj->this_->units = (MS_UNITS) units; 125 | } 126 | } else if (STRCMP(property, "projection")) { 127 | msLoadProjectionString(&(obj->this_->projection), TOSTR(value)); 128 | } else if (STRCMP(property, "type")) { 129 | int32_t type = value->Int32Value(); 130 | if (type >= MS_LAYER_ANNOTATION && type <= MS_LAYER_TILEINDEX) { 131 | obj->this_->type = (MS_LAYER_TYPE) type; 132 | } 133 | } else if (STRCMP(property, "connection")) { 134 | REPLACE_STRING(obj->this_->connection, value) 135 | } 136 | } 137 | 138 | NAN_METHOD(MSLayer::GetGridIntersectionCoordinates) { 139 | MSLayer *obj = Nan::ObjectWrap::Unwrap(info.This()); 140 | 141 | int i = 0; 142 | 143 | graticuleIntersectionObj *values = msGraticuleLayerGetIntersectionPoints(obj->this_->map, obj->this_); 144 | 145 | v8::Local left = Nan::New(values->nLeft); 146 | v8::Local top = Nan::New(values->nTop); 147 | v8::Local right = Nan::New(values->nRight); 148 | v8::Local bottom = Nan::New(values->nBottom); 149 | v8::Local val; 150 | 151 | for (i=0; inLeft; i++) { 152 | val = Nan::New(); 153 | val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasLeft[i].x)); 154 | val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasLeft[i].y)); 155 | val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszLeftLabels[i]).ToLocalChecked()); 156 | left->Set(i, val); 157 | } 158 | for (i=0; inTop; i++) { 159 | val = Nan::New(); 160 | val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasTop[i].x)); 161 | val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasTop[i].y)); 162 | val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszTopLabels[i]).ToLocalChecked()); 163 | top->Set(i, val); 164 | } 165 | for (i=0; inRight; i++) { 166 | val = Nan::New(); 167 | val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasRight[i].x)); 168 | val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasRight[i].y)); 169 | val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszRightLabels[i]).ToLocalChecked()); 170 | right->Set(i, val); 171 | } 172 | for (i=0; inBottom; i++) { 173 | val = Nan::New(); 174 | val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasBottom[i].x)); 175 | val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasBottom[i].y)); 176 | val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszBottomLabels[i]).ToLocalChecked()); 177 | bottom->Set(i, val); 178 | } 179 | 180 | // return object like this: 181 | // { 182 | // left: [{position: 0, label: '123.00'}], 183 | // top: [{position: 0, label: '123.00'}], 184 | // right: [{position: 0, label: '123.00'}], 185 | // bottom: [{position: 0, label: '123.00'}], 186 | // } 187 | v8::Local result = Nan::New(); 188 | result->Set(Nan::New("left").ToLocalChecked(), left); 189 | result->Set(Nan::New("top").ToLocalChecked(), top); 190 | result->Set(Nan::New("right").ToLocalChecked(), right); 191 | result->Set(Nan::New("bottom").ToLocalChecked(), bottom); 192 | info.GetReturnValue().Set(result); 193 | } 194 | 195 | NAN_METHOD(MSLayer::UpdateFromString) { 196 | MSLayer *obj = Nan::ObjectWrap::Unwrap(info.This()); 197 | int result; 198 | if (info.Length() < 1) { 199 | Nan::ThrowError("UpdateFromString requires one string argument"); 200 | return; 201 | } 202 | if (!info[0]->IsString()) { 203 | Nan::ThrowError("UpdateFromString requires one string argument"); 204 | return; 205 | } 206 | result = msUpdateLayerFromString(obj->this_, TOSTR(info[0]), MS_FALSE); 207 | info.GetReturnValue().Set(result); 208 | } 209 | 210 | #if MS_VERSION_NUM >= 60400 211 | NAN_METHOD(MSLayer::ToString) { 212 | MSLayer *obj = Nan::ObjectWrap::Unwrap(info.This()); 213 | char *text = msWriteLayerToString(obj->this_); 214 | info.GetReturnValue().Set(Nan::New(text).ToLocalChecked()); 215 | } 216 | #endif 217 | -------------------------------------------------------------------------------- /src/mapserver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mapserver.hpp" 4 | 5 | namespace node_mapserver { 6 | 7 | extern "C" { 8 | 9 | static void Init(v8::Local target) { 10 | 11 | MSError::Initialize(target); 12 | MSLayer::Initialize(target); 13 | MSLayers::Initialize(target); 14 | MSMap::Initialize(target); 15 | MSOutputFormat::Initialize(target); 16 | MSPoint::Initialize(target); 17 | MSProjection::Initialize(target); 18 | MSRect::Initialize(target); 19 | MSHashTable::Initialize(target); 20 | 21 | Nan::SetMethod(target, "getVersionInt", node_mapserver::getVersionInt); 22 | Nan::SetMethod(target, "getVersion", node_mapserver::getVersion); 23 | Nan::SetMethod(target, "supportsThreads", node_mapserver::supportsThreads); 24 | Nan::SetMethod(target, "resetErrorList", node_mapserver::resetErrorList); 25 | Nan::SetMethod(target, "getError", node_mapserver::getError); 26 | 27 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_ALIGN_CENTER", MS_ALIGN_CENTER); 28 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_ALIGN_LEFT", MS_ALIGN_LEFT); 29 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_ALIGN_RIGHT", MS_ALIGN_RIGHT); 30 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_AUTO", MS_AUTO); 31 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_BITMAP", MS_BITMAP); 32 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_BLUE", MS_BLUE); 33 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CC", MS_CC); 34 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_BEVEL", MS_CJC_BEVEL); 35 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_BUTT", MS_CJC_BUTT); 36 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_MITER", MS_CJC_MITER); 37 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_NONE", MS_CJC_NONE); 38 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_ROUND", MS_CJC_ROUND); 39 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_SQUARE", MS_CJC_SQUARE); 40 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CJC_TRIANGLE", MS_CJC_TRIANGLE); 41 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CL", MS_CL); 42 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_CR", MS_CR); 43 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DB_CSV", MS_DB_CSV); 44 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DB_MYSQL", MS_DB_MYSQL); 45 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DB_ORACLE", MS_DB_ORACLE); 46 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DB_POSTGRES", MS_DB_POSTGRES); 47 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DB_XBASE", MS_DB_XBASE); 48 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DD", MS_DD); 49 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DEFAULT", MS_DEFAULT); 50 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DELETE", MS_DELETE); 51 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_DONE", MS_DONE); 52 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_EMBED", MS_EMBED); 53 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FAILURE", MS_FAILURE); 54 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FALSE", MS_FALSE); 55 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FEET", MS_FEET); 56 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FILE", MS_FILE); 57 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FILE_MAP", MS_FILE_MAP); 58 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_FILE_SYMBOL", MS_FILE_SYMBOL); 59 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_BEYOND", MS_GEOS_BEYOND); 60 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_CONTAINS", MS_GEOS_CONTAINS); 61 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_CROSSES", MS_GEOS_CROSSES); 62 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_DISJOINT", MS_GEOS_DISJOINT); 63 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_DWITHIN", MS_GEOS_DWITHIN); 64 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_EQUALS", MS_GEOS_EQUALS); 65 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_INTERSECTS", MS_GEOS_INTERSECTS); 66 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_OVERLAPS", MS_GEOS_OVERLAPS); 67 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_TOUCHES", MS_GEOS_TOUCHES); 68 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GEOS_WITHIN", MS_GEOS_WITHIN); 69 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GIANT", MS_GIANT); 70 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GRATICULE", MS_GRATICULE); 71 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_GREEN", MS_GREEN); 72 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_HILITE", MS_HILITE); 73 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_BYTE", MS_IMAGEMODE_BYTE); 74 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_FLOAT32", MS_IMAGEMODE_FLOAT32); 75 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_INT16", MS_IMAGEMODE_INT16); 76 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_NULL", MS_IMAGEMODE_NULL); 77 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_PC256", MS_IMAGEMODE_PC256); 78 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_RGB", MS_IMAGEMODE_RGB); 79 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_IMAGEMODE_RGBA", MS_IMAGEMODE_RGBA); 80 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_INCHES", MS_INCHES); 81 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_INLINE", MS_INLINE); 82 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_JOIN_ONE_TO_MANY", MS_JOIN_ONE_TO_MANY); 83 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_JOIN_ONE_TO_ONE", MS_JOIN_ONE_TO_ONE); 84 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_KILOMETERS", MS_KILOMETERS); 85 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LARGE", MS_LARGE); 86 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_ANNOTATION", MS_LAYER_ANNOTATION); 87 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_CHART", MS_LAYER_CHART); 88 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_CIRCLE", MS_LAYER_CIRCLE); 89 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_LINE", MS_LAYER_LINE); 90 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_POINT", MS_LAYER_POINT); 91 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_POLYGON", MS_LAYER_POLYGON); 92 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_QUERY", MS_LAYER_QUERY); 93 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_RASTER", MS_LAYER_RASTER); 94 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LAYER_TILEINDEX", MS_LAYER_TILEINDEX); 95 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LC", MS_LC); 96 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LL", MS_LL); 97 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_LR", MS_LR); 98 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_MAXCOLORS", MS_MAXCOLORS); 99 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_MEDIUM", MS_MEDIUM); 100 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_METERS", MS_METERS); 101 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_MILES", MS_MILES); 102 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_MULTIPLE", MS_MULTIPLE); 103 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_NAUTICALMILES", MS_NAUTICALMILES); 104 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_NO", MS_NO); 105 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_NORMAL", MS_NORMAL); 106 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_OFF", MS_OFF); 107 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_OGR", MS_OGR); 108 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_ON", MS_ON); 109 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_ORACLESPATIAL", MS_ORACLESPATIAL); 110 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_PERCENTAGES", MS_PERCENTAGES); 111 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_PIXELS", MS_PIXELS); 112 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_PLUGIN", MS_PLUGIN); 113 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_POSTGIS", MS_POSTGIS); 114 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_BY_ATTRIBUTE", MS_QUERY_BY_ATTRIBUTE); 115 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_BY_INDEX", MS_QUERY_BY_INDEX); 116 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_BY_POINT", MS_QUERY_BY_POINT); 117 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_BY_RECT", MS_QUERY_BY_RECT); 118 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_BY_SHAPE", MS_QUERY_BY_SHAPE); 119 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_IS_NULL", MS_QUERY_IS_NULL); 120 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_MULTIPLE", MS_QUERY_MULTIPLE); 121 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_QUERY_SINGLE", MS_QUERY_SINGLE); 122 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_RASTER", MS_RASTER); 123 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_RED", MS_RED); 124 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SDE", MS_SDE); 125 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SELECTED", MS_SELECTED); 126 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SHAPEFILE", MS_SHAPEFILE); 127 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SHAPE_LINE", MS_SHAPE_LINE); 128 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SHAPE_NULL", MS_SHAPE_NULL); 129 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SHAPE_POINT", MS_SHAPE_POINT); 130 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SHAPE_POLYGON", MS_SHAPE_POLYGON); 131 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SINGLE", MS_SINGLE); 132 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SMALL", MS_SMALL); 133 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_SUCCESS", MS_SUCCESS); 134 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_TILED_SHAPEFILE", MS_TILED_SHAPEFILE); 135 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_TINY ", MS_TINY ); 136 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_TRUE", MS_TRUE); 137 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_TRUETYPE", MS_TRUETYPE); 138 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_UC", MS_UC); 139 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_UL", MS_UL); 140 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_UNKNOWN", MS_UNKNOWN); 141 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_UNUSED_1", MS_UNUSED_1); 142 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_UR", MS_UR); 143 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_URL", MS_URL); 144 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_WFS", MS_WFS); 145 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_WMS", MS_WMS); 146 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_XY", MS_XY); 147 | NODE_MAPSERVER_DEFINE_CONSTANT(target, "MS_YES", MS_YES); 148 | 149 | } 150 | } 151 | } 152 | 153 | NODE_MODULE(mapserver, node_mapserver::Init); -------------------------------------------------------------------------------- /src/ms_map.cpp: -------------------------------------------------------------------------------- 1 | #include "ms_map.hpp" 2 | 3 | Nan::Persistent MSMap::constructor; 4 | 5 | void MSMap::Initialize(v8::Local target) { 6 | v8::Local tpl = Nan::New(MSMap::New); 7 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 8 | tpl->SetClassName(Nan::New("Map").ToLocalChecked()); 9 | 10 | Nan::SetPrototypeMethod(tpl, "clone", Clone); 11 | Nan::SetPrototypeMethod(tpl, "selectOutputFormat", SelectOutputFormat); 12 | Nan::SetPrototypeMethod(tpl, "setExtent", SetExtent); 13 | Nan::SetPrototypeMethod(tpl, "drawMap", DrawMap); 14 | Nan::SetPrototypeMethod(tpl, "recompute", Recompute); 15 | Nan::SetPrototypeMethod(tpl, "insertLayer", InsertLayer); 16 | Nan::SetPrototypeMethod(tpl, "setSymbolSet", SetSymbolSet); 17 | Nan::SetPrototypeMethod(tpl, "save", Save); 18 | Nan::SetPrototypeMethod(tpl, "getLabelCache", GetLabelCache); 19 | 20 | /* Read-Write Properties */ 21 | RW_ATTR(tpl, "name", PropertyGetter, PropertySetter); 22 | RW_ATTR(tpl, "status", PropertyGetter, PropertySetter); 23 | RW_ATTR(tpl, "width", PropertyGetter, PropertySetter); 24 | RW_ATTR(tpl, "height", PropertyGetter, PropertySetter); 25 | RW_ATTR(tpl, "maxsize", PropertyGetter, PropertySetter); 26 | RW_ATTR(tpl, "units", PropertyGetter, PropertySetter); 27 | RW_ATTR(tpl, "resolution", PropertyGetter, PropertySetter); 28 | RW_ATTR(tpl, "defresolution", PropertyGetter, PropertySetter); 29 | RW_ATTR(tpl, "shapepath", PropertyGetter, PropertySetter); 30 | RW_ATTR(tpl, "mappath", PropertyGetter, PropertySetter); 31 | RW_ATTR(tpl, "imagetype", PropertyGetter, PropertySetter); 32 | RW_ATTR(tpl, "projection", PropertyGetter, PropertySetter); 33 | 34 | /* Read-Only Properties */ 35 | RO_ATTR(tpl, "cellsize", PropertyGetter); 36 | RO_ATTR(tpl, "scaledenom", PropertyGetter); 37 | RO_ATTR(tpl, "mimetype", PropertyGetter); 38 | RO_ATTR(tpl, "outputformat", PropertyGetter); 39 | RO_ATTR(tpl, "metadata", PropertyGetter); 40 | RO_ATTR(tpl, "extent", PropertyGetter); 41 | RO_ATTR(tpl, "layers", PropertyGetter); 42 | 43 | target->Set(Nan::New("Map").ToLocalChecked(), tpl->GetFunction()); 44 | constructor.Reset(tpl); 45 | } 46 | 47 | MSMap::MSMap(mapObj *map) : ObjectWrap(), this_(map) {} 48 | 49 | MSMap::MSMap() : ObjectWrap(), this_(0) {} 50 | 51 | MSMap::~MSMap() { 52 | if (this_) { 53 | msFreeMap(this_); 54 | this_ = NULL; 55 | } 56 | } 57 | 58 | NAN_METHOD(MSMap::New) { 59 | mapObj *map; 60 | MSMap *obj; 61 | 62 | if (!info.IsConstructCall()) { 63 | Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword"); 64 | return; 65 | } 66 | 67 | if (info[0]->IsExternal()) { 68 | v8::Local ext = info[0].As(); 69 | void* ptr = ext->Value(); 70 | obj = static_cast(ptr); 71 | obj->Wrap(info.This()); 72 | info.GetReturnValue().Set(info.This()); 73 | return; 74 | } 75 | 76 | if (info.Length() == 2) { 77 | if (!ISSTR(info, 0) || !ISSTR(info, 1)) { 78 | Nan::ThrowTypeError("Map constructor takes one or two string arguments"); 79 | return; 80 | } 81 | map = msLoadMap(TOSTR(info[0]), TOSTR(info[1])); 82 | } else if (info.Length() == 1) { 83 | if (!ISSTR(info, 0)) { 84 | Nan::ThrowTypeError("Map constructor takes one or two string arguments"); 85 | return; 86 | } 87 | map = msLoadMap(TOSTR(info[0]), NULL); 88 | } else { 89 | map = msNewMapObj(); 90 | } 91 | 92 | if (map == NULL) { 93 | Nan::ThrowError("Unable to load requested map."); 94 | return; 95 | } 96 | 97 | obj = new MSMap(map); 98 | obj->Wrap(info.This()); 99 | info.GetReturnValue().Set(info.This()); 100 | } 101 | 102 | v8::Local MSMap::NewInstance(mapObj *ptr) { 103 | Nan::EscapableHandleScope scope; 104 | MSMap* obj = new MSMap(); 105 | obj->this_ = ptr; 106 | v8::Local ext = Nan::New(obj); 107 | return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext)); 108 | } 109 | 110 | NAN_METHOD(MSMap::Clone) { 111 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 112 | mapObj * _copy = msNewMapObj(); 113 | if (msCopyMap(_copy, map->this_) == MS_SUCCESS) { 114 | info.GetReturnValue().Set(MSMap::NewInstance(_copy)); 115 | } 116 | } 117 | 118 | 119 | NAN_METHOD(MSMap::SetExtent) { 120 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 121 | if (info.Length() != 4) { 122 | Nan::ThrowError("SetExtent requires 4 numeric arguments"); 123 | return; 124 | } 125 | 126 | if (!info[0]->IsNumber() || !info[1]->IsNumber() || !info[2]->IsNumber() || !info[3]->IsNumber()) { 127 | Nan::ThrowError("SetExtent requires 4 numeric arguments"); 128 | return; 129 | } 130 | 131 | map->this_->extent.minx = Nan::To(info[0]).FromJust(); 132 | map->this_->extent.miny = Nan::To(info[1]).FromJust(); 133 | map->this_->extent.maxx = Nan::To(info[2]).FromJust(); 134 | map->this_->extent.maxy = Nan::To(info[3]).FromJust(); 135 | 136 | info.GetReturnValue().Set(Nan::True()); 137 | } 138 | 139 | NAN_METHOD(MSMap::Recompute) { 140 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 141 | mapObj *_map = map->this_; 142 | _map->cellsize = msAdjustExtent(&(_map->extent), 143 | _map->width, 144 | _map->height); 145 | msCalculateScale(_map->extent, 146 | _map->units, 147 | _map->width, 148 | _map->height, 149 | _map->resolution, 150 | &_map->scaledenom); 151 | info.GetReturnValue().Set(Nan::True()); 152 | } 153 | 154 | NAN_METHOD(MSMap::InsertLayer) { 155 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 156 | MSLayer *layer; 157 | v8::Local obj; 158 | int result; 159 | int position = -1; 160 | 161 | if (info.Length() < 1) { 162 | Nan::ThrowError("insertLayer requires at least one argument"); 163 | return; 164 | } 165 | 166 | if (!info[0]->IsObject()) { 167 | Nan::ThrowTypeError("first argument to project must be Layer object"); 168 | return; 169 | } 170 | 171 | obj = info[0]->ToObject(); 172 | 173 | if (obj->IsNull() || obj->IsUndefined() || !Nan::New(MSLayer::constructor)->HasInstance(obj)) { 174 | Nan::ThrowTypeError("first argument to project must be Layer object"); 175 | return; 176 | } 177 | 178 | layer = Nan::ObjectWrap::Unwrap(obj); 179 | 180 | if (info.Length() == 2) { 181 | if (!info[1]->IsNumber()) { 182 | Nan::ThrowTypeError("second argument must be an integer"); 183 | return; 184 | } else { 185 | position = Nan::To(info[1]).FromJust(); 186 | if (position >= map->this_->numlayers) { 187 | position = -1; 188 | } 189 | } 190 | } 191 | result = msInsertLayer(map->this_, layer->this_, position); 192 | info.GetReturnValue().Set(result); 193 | } 194 | 195 | NAN_METHOD(MSMap::SelectOutputFormat) { 196 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 197 | if (info.Length() != 1 || !info[0]->IsString()) { 198 | Nan::ThrowTypeError("selectOuptutFormat requires a string argument"); 199 | return; 200 | } 201 | outputFormatObj * format = msSelectOutputFormat(map->this_, TOSTR(info[0])); 202 | if ( format == NULL) { 203 | Nan::ThrowError("Output format not supported."); 204 | return; 205 | } 206 | msApplyOutputFormat(&(map->this_->outputformat), format, MS_NOOVERRIDE, 207 | MS_NOOVERRIDE, MS_NOOVERRIDE ); 208 | } 209 | 210 | NAN_METHOD(MSMap::SetSymbolSet) { 211 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 212 | int result; 213 | 214 | if (info.Length() != 1 || !info[0]->IsString()) { 215 | Nan::ThrowTypeError("SetSymbolSet requires a string argument"); 216 | return; 217 | } 218 | 219 | msFreeSymbolSet(&(map->this_->symbolset)); 220 | msInitSymbolSet(&(map->this_->symbolset)); 221 | 222 | // Set symbolset filename 223 | map->this_->symbolset.filename = strdup(TOSTR(info[0])); 224 | 225 | // Symbolset shares same fontset as main mapfile 226 | map->this_->symbolset.fontset = &(map->this_->fontset); 227 | 228 | result = msLoadSymbolSet(&(map->this_->symbolset), map->this_); 229 | info.GetReturnValue().Set(result); 230 | } 231 | 232 | NAN_METHOD(MSMap::Save) { 233 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 234 | int result; 235 | if (info.Length() != 1 || !info[0]->IsString()) { 236 | Nan::ThrowTypeError("Save requires a string argument"); 237 | return; 238 | } 239 | 240 | result = msSaveMap(map->this_, TOSTR(info[0])); 241 | info.GetReturnValue().Set(result); 242 | } 243 | 244 | NAN_METHOD(MSMap::GetLabelCache) { 245 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 246 | 247 | labelCacheObj *labelcache = &(map->this_->labelcache); 248 | 249 | #if MS_VERSION_NUM < 60500 250 | labelCacheSlotObj *cacheslot; 251 | int numLabels = 0; 252 | int k = 0; 253 | size_t i = 0; 254 | size_t j = 0; 255 | for(i = 0; i < MS_MAX_LABEL_PRIORITY; ++i) { 256 | cacheslot = &(labelcache->slots[i]); 257 | for(size_t j = 0; j < cacheslot->numlabels; ++j) { 258 | if (cacheslot->labels[j].status == MS_ON) { 259 | numLabels ++; 260 | } 261 | } 262 | } 263 | v8::Local labels = Nan::New(numLabels); 264 | for(i = 0; i < MS_MAX_LABEL_PRIORITY; ++i) { 265 | cacheslot = &(labelcache->slots[i]); 266 | v8::Local labels = Nan::New(cacheslot->numlabels); 267 | for(j = 0; j < cacheslot->numlabels; ++j) { 268 | v8::Local label = Nan::New(); 269 | Nan::Set(label, Nan::New("status").ToLocalChecked(), Nan::New(MS_ON)); 270 | Nan::Set(label, Nan::New("x").ToLocalChecked(), Nan::New(cacheslot->labels[j].point.x)); 271 | Nan::Set(label, Nan::New("y").ToLocalChecked(), Nan::New(cacheslot->labels[j].point.y)); 272 | Nan::Set(label, Nan::New("text").ToLocalChecked(), Nan::New(cacheslot->labels[j].labels[0].annotext).ToLocalChecked()); 273 | Nan::Set(label, Nan::New("layerindex").ToLocalChecked(), Nan::New(cacheslot->labels[j].layerindex)); 274 | Nan::Set(label, Nan::New("classindex").ToLocalChecked(), Nan::New(cacheslot->labels[j].classindex)); 275 | Nan::Set(labels, k++, label); 276 | } 277 | } 278 | #else 279 | v8::Local labels = Nan::New(labelcache->num_rendered_members); 280 | int p = 0; 281 | for (p=0; pnum_rendered_members; p++) { 282 | labelCacheMemberObj* curCachePtr = labelcache->rendered_text_symbols[p]; 283 | v8::Local label = Nan::New(); 284 | Nan::Set(label, Nan::New("status").ToLocalChecked(), Nan::New(MS_ON)); 285 | Nan::Set(label, Nan::New("x").ToLocalChecked(), Nan::New(curCachePtr->point.x)); 286 | Nan::Set(label, Nan::New("y").ToLocalChecked(), Nan::New(curCachePtr->point.y)); 287 | if ((curCachePtr->textsymbols[0]->annotext) == NULL) { 288 | Nan::Set(label, Nan::New("text").ToLocalChecked(), Nan::New("").ToLocalChecked()); 289 | } else { 290 | Nan::Set(label, Nan::New("text").ToLocalChecked(), Nan::New(curCachePtr->textsymbols[0]->annotext).ToLocalChecked()); 291 | } 292 | Nan::Set(label, Nan::New("layerindex").ToLocalChecked(), Nan::New(curCachePtr->layerindex)); 293 | Nan::Set(label, Nan::New("classindex").ToLocalChecked(), Nan::New(curCachePtr->classindex)); 294 | Nan::Set(labels, p, label); 295 | } 296 | #endif 297 | 298 | // return an array of rendered labels 299 | info.GetReturnValue().Set(labels); 300 | } 301 | 302 | NAN_GETTER(MSMap::PropertyGetter) { 303 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 304 | 305 | if (STRCMP(property, "width")) { 306 | info.GetReturnValue().Set(map->this_->width); 307 | } else if (STRCMP(property, "height")) { 308 | info.GetReturnValue().Set(map->this_->height); 309 | } else if (STRCMP(property, "status")) { 310 | info.GetReturnValue().Set(map->this_->status); 311 | } else if (STRCMP(property, "maxsize")) { 312 | info.GetReturnValue().Set(map->this_->maxsize); 313 | } else if (STRCMP(property, "cellsize")) { 314 | info.GetReturnValue().Set(map->this_->cellsize); 315 | } else if (STRCMP(property, "units")) { 316 | info.GetReturnValue().Set(map->this_->units); 317 | } else if (STRCMP(property, "scaledenom")) { 318 | info.GetReturnValue().Set(map->this_->scaledenom); 319 | } else if (STRCMP(property, "resolution")) { 320 | info.GetReturnValue().Set(map->this_->resolution); 321 | } else if (STRCMP(property, "defresolution")) { 322 | info.GetReturnValue().Set(map->this_->defresolution); 323 | } else if (STRCMP(property, "imagetype")) { 324 | info.GetReturnValue().Set(Nan::New(map->this_->imagetype).ToLocalChecked()); 325 | } else if (STRCMP(property, "mimetype")) { 326 | info.GetReturnValue().Set(Nan::New(map->this_->outputformat->mimetype).ToLocalChecked()); 327 | } else if (STRCMP(property, "shapepath")) { 328 | info.GetReturnValue().Set(Nan::New(map->this_->shapepath).ToLocalChecked()); 329 | } else if (STRCMP(property, "mappath")) { 330 | info.GetReturnValue().Set(Nan::New(map->this_->mappath).ToLocalChecked()); 331 | } else if (STRCMP(property, "name")) { 332 | info.GetReturnValue().Set(Nan::New(map->this_->name).ToLocalChecked()); 333 | } else if (STRCMP(property, "outputformat")) { 334 | info.GetReturnValue().Set(MSOutputFormat::NewInstance(map->this_->outputformat)); 335 | } else if (STRCMP(property, "projection")) { 336 | info.GetReturnValue().Set(MSProjection::NewInstance(&map->this_->projection)); 337 | } else if (STRCMP(property, "layers")) { 338 | info.GetReturnValue().Set(MSLayers::NewInstance(map->this_)); 339 | } else if (STRCMP(property, "metadata")) { 340 | #if MS_VERSION_NUM < 60400 341 | info.GetReturnValue().Set(Nan::New()); 342 | #else 343 | info.GetReturnValue().Set(MSHashTable::NewInstance(&(map->this_->web.metadata))); 344 | #endif 345 | } else if (STRCMP(property, "extent")) { 346 | info.GetReturnValue().Set(MSRect::NewInstance(&map->this_->extent)); 347 | } 348 | } 349 | 350 | NAN_SETTER(MSMap::PropertySetter) { 351 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 352 | 353 | if (STRCMP(property, "width")) { 354 | map->this_->width = value->Int32Value(); 355 | } else if (STRCMP(property, "height")) { 356 | map->this_->height = value->Int32Value(); 357 | } else if (STRCMP(property, "maxsize")) { 358 | map->this_->maxsize = value->Int32Value(); 359 | } else if (STRCMP(property, "units")) { 360 | int32_t units = value->Int32Value(); 361 | if (units >= MS_INCHES && units <= MS_NAUTICALMILES) { 362 | map->this_->units = (MS_UNITS) units; 363 | } 364 | } else if (STRCMP(property, "resolution")) { 365 | map->this_->resolution = value->NumberValue(); 366 | } else if (STRCMP(property, "defresolution")) { 367 | map->this_->defresolution = value->NumberValue(); 368 | } else if (STRCMP(property, "name")) { 369 | REPLACE_STRING(map->this_->name, value); 370 | } else if (STRCMP(property, "imagetype")) { 371 | REPLACE_STRING(map->this_->imagetype, value); 372 | } else if (STRCMP(property, "shapepath")) { 373 | REPLACE_STRING(map->this_->shapepath, value); 374 | } else if (STRCMP(property, "projection")) { 375 | msLoadProjectionString(&(map->this_->projection), TOSTR(value)); 376 | } else if (STRCMP(property, "mappath")) { 377 | REPLACE_STRING(map->this_->mappath, value); 378 | } 379 | } 380 | 381 | struct drawmap_baton { 382 | uv_work_t request; 383 | MSMap *map; 384 | errorObj * error; 385 | int size; 386 | char * data; 387 | Nan::Persistent cb; 388 | }; 389 | 390 | void FreeImageBuffer(char *data, void *hint) { 391 | msFree(data); 392 | } 393 | 394 | void MSMap::EIO_DrawMap(uv_work_t *req) { 395 | drawmap_baton *baton = static_cast(req->data); 396 | 397 | imageObj * im = msDrawMap(baton->map->this_, MS_FALSE); 398 | 399 | if (im != NULL) { 400 | baton->error = NULL; 401 | baton->data = (char *)msSaveImageBuffer(im, &baton->size, baton->map->this_->outputformat); 402 | msFreeImage(im); 403 | } else { 404 | baton->error = msGetErrorObj(); 405 | baton->data = NULL; 406 | } 407 | } 408 | 409 | void MSMap::EIO_AfterDrawMap(uv_work_t *req) { 410 | Nan::HandleScope scope; 411 | 412 | drawmap_baton *baton = static_cast(req->data); 413 | 414 | if (baton->data != NULL) { 415 | v8::Local buffer = Nan::NewBuffer(baton->data, baton->size, FreeImageBuffer, NULL).ToLocalChecked(); 416 | v8::Local argv[2] = { Nan::Null(), buffer }; 417 | Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->cb), 2, argv); 418 | } else { 419 | v8::Local argv[1] = { MSError::NewInstance(baton->error) }; 420 | Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(baton->cb), 1, argv); 421 | } 422 | 423 | baton->map->Unref(); 424 | baton->cb.Reset(); 425 | delete baton; 426 | } 427 | 428 | /** 429 | * callback for buffer creation to free the memory assocatiated with the 430 | * image after its been copied into the buffer 431 | */ 432 | 433 | NAN_METHOD(MSMap::DrawMap) { 434 | MSMap *map = Nan::ObjectWrap::Unwrap(info.Holder()); 435 | 436 | if (info.Length() != 1) { 437 | Nan::ThrowTypeError("DrawMap missing callback function"); 438 | return; 439 | } 440 | 441 | if (!info[0]->IsFunction()) { 442 | Nan::ThrowTypeError("DrawMap requires a single function argument"); 443 | return; 444 | } 445 | 446 | char * version = msGetVersion(); 447 | int match; 448 | match = 0; 449 | if (msEvalRegex("SUPPORTS\\=THREADS", version) == MS_TRUE) { 450 | match = 1; 451 | } else { 452 | // discard the error reported by msEvalRegex saying that it failed 453 | msResetErrorList(); 454 | } 455 | 456 | 457 | if (match == 1) { 458 | drawmap_baton * baton = new drawmap_baton(); 459 | baton->request.data = (void*) baton; 460 | baton->map = map; 461 | baton->cb.Reset(info[0].As()); 462 | 463 | map->Ref(); 464 | uv_queue_work(uv_default_loop(), 465 | &baton->request, 466 | EIO_DrawMap, 467 | (uv_after_work_cb) EIO_AfterDrawMap); 468 | } else { 469 | v8::Local argv[2]; 470 | argv[0] = Nan::Null(); 471 | imageObj * im = msDrawMap(map->this_, MS_FALSE); 472 | 473 | if (im != NULL) { 474 | int size; 475 | char * data = (char *)msSaveImageBuffer(im, &size, map->this_->outputformat); 476 | msFreeImage(im); 477 | argv[1] = Nan::NewBuffer(data, size, FreeImageBuffer, NULL).ToLocalChecked(); 478 | } else { 479 | errorObj * err = msGetErrorObj(); 480 | argv[0] = MSError::NewInstance(err); 481 | argv[1] = Nan::Null(); 482 | } 483 | Nan::MakeCallback(Nan::GetCurrentContext()->Global(), info[0].As(), 2, argv); 484 | } 485 | } -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Paul Spencer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | 18 | /*jshint node:true, sub:true */ 19 | /*global beforeEach, describe, it */ 20 | 21 | "use strict"; 22 | 23 | 24 | var assert = require('assert'); 25 | var util = require('util'); 26 | var mapserver = require('../mapserver'); 27 | var fs = require('fs'); 28 | var path = require('path'); 29 | var datadir = path.join(__dirname, 'data'); 30 | var mapfile = path.join(datadir, 'test.map'); 31 | var symbolfile = path.join(datadir, 'symbolset.txt'); 32 | var nomapfile = 'missing.map'; 33 | var map; 34 | var layer; 35 | var err; 36 | 37 | console.log('running tests for mapserver %s : %s', mapserver.getVersionInt(), mapserver.getVersion()); 38 | 39 | beforeEach(function() { 40 | mapserver.resetErrorList(); 41 | }); 42 | 43 | describe('mapserver', function() { 44 | it('should exports constants', function() { 45 | // test constants 46 | assert.equal(mapserver.MS_OFF, 0, 'MS_OFF not defined'); 47 | assert.equal(mapserver.MS_ON, 1, 'MS_ON not defined'); 48 | }); 49 | 50 | it('should get some basic info about mapserver', function() { 51 | assert.ok(mapserver.getVersionInt(), 'mapserver should report its version number'); 52 | assert.ok(mapserver.getVersion(), 'mapserver should report its version string'); 53 | assert.ok(mapserver.supportsThreads(), 'mapserver compiled without thread support.'); 54 | }); 55 | 56 | it('should have no errors yet', function() { 57 | // quick error test 58 | var err = mapserver.getError(); 59 | assert.equal(err.code, 0, 'should be no errors'); 60 | }); 61 | 62 | it('should create a projection', function() { 63 | // quick error test 64 | var proj = new mapserver.Projection("+init=epsg:4326"); 65 | assert.equal(proj.units, mapserver.MS_DD, 'projection units should be decimal degrees'); 66 | assert.equal(proj.projString, "+init=epsg:4326", 'getting projection string failed. Got ' + proj.projString); 67 | err = mapserver.getError(); 68 | assert.equal(err.code, 0, 'should be no errors'); 69 | proj.projString = "+init=epsg:3857"; 70 | assert.equal(proj.projString, "+init=epsg:3857", 'setting projection object via string failed. Got ' + proj.projString); 71 | }); 72 | 73 | it('should have a functional point object', function() { 74 | var point = new mapserver.Point(); 75 | assert.equal(point.x, -1, 'default point x should be -1'); 76 | assert.equal(point.y, -1, 'default point y should be -1'); 77 | 78 | point = new mapserver.Point(10.5, 20); 79 | assert.equal(point.x, 10.5, 'create a point with an x and y value'); 80 | assert.equal(point.y, 20, 'create a point with an x and y value'); 81 | 82 | var epsg4326 = new mapserver.Projection("+init=epsg:4326"); 83 | var epsg3857 = new mapserver.Projection("+init=epsg:3857"); 84 | point.project(epsg4326, epsg3857); 85 | 86 | var dx = Math.abs(point.x - 1168854.6533293733).toFixed(6); 87 | assert.equal(dx, 0, 'reprojected x was not correct, delta was ' + dx); 88 | var dy = Math.abs(point.y - 2273030.926987688).toFixed(6); 89 | assert.equal(dy, 0, 'reprojected y was not correct, delta was ' + dy); 90 | point = new mapserver.Point(0,0); 91 | assert.equal(point.distanceToPoint(new mapserver.Point(1,0)), 1, 'distanceToPoint should be 1'); 92 | }); 93 | 94 | it('should have a functional rect object', function() { 95 | var rect; 96 | 97 | assert.doesNotThrow(function() { 98 | rect = new mapserver.Rect(); 99 | }, 'creating a rect with 0 arguments should work.'); 100 | 101 | assert.equal(rect.minx, -1, 'default rect constructor minx should equal -1'); 102 | assert.equal(rect.miny, -1, 'default rect constructor miny should equal -1'); 103 | assert.equal(rect.maxx, -1, 'default rect constructor maxx should equal -1'); 104 | assert.equal(rect.maxy, -1, 'default rect constructor maxy should equal -1'); 105 | 106 | assert.doesNotThrow(function() { 107 | rect = new mapserver.Rect(1.2, 3.4, 5.6, 7.8); 108 | }, 'creating a rect with 4 arguments should work'); 109 | 110 | assert.equal(rect.minx, 1.2, 'rect minx should equal 1.2'); 111 | assert.equal(rect.miny, 3.4, 'rect miny should equal 3.4'); 112 | assert.equal(rect.maxx, 5.6, 'rect maxx should equal 5.6'); 113 | assert.equal(rect.maxy, 7.8, 'rect maxy should equal 7.8'); 114 | 115 | assert['throws'](function() { 116 | rect = new mapserver.Rect(1,1); 117 | }, Error, 'rect constructor should throw an error with wrong number of arguments.'); 118 | 119 | assert['throws'](function() { 120 | rect = new mapserver.Rect('a', 'b', 'c', 'd'); 121 | console.log(rect); 122 | }, Error, 'rect constructor should throw an error with wrong argument type.'); 123 | 124 | rect = new mapserver.Rect(3, 4, 1, 2); 125 | assert.equal(rect.minx, 1, 'rect minx should be minimum x value'); 126 | assert.equal(rect.miny, 2, 'rect miny should be minimum y value'); 127 | assert.equal(rect.maxx, 3, 'rect maxx should be maximum x value'); 128 | assert.equal(rect.maxy, 4, 'rect maxy should be maximum y value'); 129 | 130 | rect = new mapserver.Rect(); 131 | rect.minx = 1; 132 | rect.miny = 2; 133 | rect.maxx = 3; 134 | rect.maxy = 4; 135 | assert.equal(rect.minx, 1, 'rect minx should assignable'); 136 | assert.equal(rect.miny, 2, 'rect miny should assignable'); 137 | assert.equal(rect.maxx, 3, 'rect maxx should assignable'); 138 | assert.equal(rect.maxy, 4, 'rect maxy should assignable'); 139 | 140 | assert['throws'](function() { 141 | rect = new mapserver.Rect(0, 0, 1, 1); 142 | rect.project('a','b'); 143 | }, Error, 'rect project should throw an error with wrong argument type.'); 144 | rect = new mapserver.Rect(0, 0, 1, 1); 145 | rect.project(new mapserver.Projection('+init=epsg:4326'), new mapserver.Projection('+init=epsg:3857')); 146 | 147 | var delta = Math.abs(rect.minx - 0).toFixed(6); 148 | assert.equal(delta, 0, 'reprojecting rect minx failed, delta was ' + delta); 149 | delta = Math.abs(rect.miny - 0).toFixed(6); 150 | assert.equal(delta, 0, 'reprojecting rect miny failed, delta was ' + delta); 151 | delta = Math.abs(rect.maxx - 111319.49079327231).toFixed(6); 152 | assert.equal(delta, 0, 'reprojecting rect maxx failed, delta was ' + delta); 153 | delta = Math.abs(rect.maxy - 111325.14286638486).toFixed(6); 154 | assert.equal(delta, 0, 'reprojecting rect maxy failed, delta was ' + delta); 155 | }); 156 | 157 | it('should throw an error for a missing mapfile', function() { 158 | // Test default mapfile pattern (must end in .map) 159 | assert['throws'](function() { 160 | new mapserver.Map(nomapfile); 161 | }, Error, 'attempting to load a non-existent map should throw an error.'); 162 | 163 | // check error 164 | err = mapserver.getError(); 165 | assert.equal(err.code, 1, 'Missing map file error failed.'); 166 | 167 | // test resetErrorList 168 | mapserver.resetErrorList(); 169 | err = mapserver.getError(); 170 | assert.equal(err.code, 0, 'should be able to reset the error list'); 171 | }); 172 | 173 | it('should load a valid map file', function() { 174 | assert.doesNotThrow(function() { 175 | map = new mapserver.Map(mapfile, __dirname); 176 | }, function() { 177 | err = mapserver.getError(); 178 | console.log(util.inspect(err)); 179 | }, 'loading a valid map file with a data path should not throw an error.'); 180 | assert.equal(map.mappath, __dirname, 'map did not load with correct data directory'); 181 | 182 | assert.doesNotThrow(function() { 183 | map = new mapserver.Map(mapfile); 184 | }, function() { 185 | err = mapserver.getError(); 186 | console.log(util.inspect(err)); 187 | }, 'loading a valid map file with no data path should not throw an error.'); 188 | assert.equal(path.relative(map.mappath, path.dirname(mapfile)), '', 'map did not compute correct default data directory'); 189 | 190 | assert.doesNotThrow(function() { 191 | map = new mapserver.Map(); 192 | }, function() { 193 | err = mapserver.getError(); 194 | console.log(util.inspect(err)); 195 | }, 'creating a blank map should not throw an error'); 196 | }); 197 | 198 | it('should get basic information from the map object', function() { 199 | assert.doesNotThrow(function() { 200 | map = new mapserver.Map(mapfile); 201 | }, Error, 'loading a valid map file should not throw an error.'); 202 | 203 | assert.equal(map.name, "GMAP_DEMO", 'map name is incorrect'); 204 | assert.equal(map.status, mapserver.MS_ON, 'map status is not ON'); 205 | assert.equal(map.width, 600, 'getting map width failed'); 206 | assert.equal(map.height, 300, 'getting map height failed'); 207 | assert.equal(map.cellsize, 0, 'default map cellsize should be 0, got ' + map.cellsize); 208 | assert.equal(map.scaledenom, -1, 'default map scaledenom should be -1, got ' + map.scaledenom); 209 | assert.equal(map.maxsize, 2048, 'getting map maxsize failed'); 210 | assert.equal(map.units, mapserver.MS_DD, 'getting map units failed'); 211 | assert.equal(map.resolution, 72, 'getting map resolution failed'); 212 | assert.equal(map.defresolution, 72, 'getting map defresolution failed'); 213 | assert.equal(map.shapepath, './', 'getting shapepath failed'); 214 | assert.equal(map.imagetype, 'png', 'imagetype should be png, got ' + map.imagetype); 215 | assert.equal(map.mimetype, 'image/png', 'mimetype should be image/png, got ' + map.mimetype); 216 | }); 217 | 218 | it('should set map properties', function() { 219 | assert.doesNotThrow(function() { 220 | map = new mapserver.Map(mapfile); 221 | }, Error, 'loading a valid map file should not throw an error.'); 222 | 223 | // test setting map properties 224 | map.name = "test_set"; 225 | assert.equal(map.name, "test_set", "map name could not be set"); 226 | 227 | map.width = 600; 228 | assert.equal(map.width, 600, 'setting map width failed'); 229 | 230 | map.height = 600; 231 | assert.equal(map.height, 600, 'setting map height failed'); 232 | map.height = 300; 233 | assert.equal(map.height, 300, 'resetting map height failed'); 234 | 235 | map.maxsize = 4096; 236 | assert.equal(map.maxsize, 4096, 'setting map maxsize failed'); 237 | 238 | map.units = mapserver.MS_FEET; 239 | assert.equal(map.units, mapserver.MS_FEET, 'setting map units failed'); 240 | 241 | map.resolution = 96; 242 | assert.equal(map.resolution, 96, 'setting map defresolution failed'); 243 | 244 | map.defresolution = 96; 245 | assert.equal(map.defresolution, 96, 'setting map defresolution failed'); 246 | 247 | }); 248 | 249 | it('should clone a map object', function() { 250 | assert.doesNotThrow(function() { 251 | map = new mapserver.Map(mapfile); 252 | }, Error, 'loading a valid map file should not throw an error.'); 253 | 254 | var clone = map.clone(); 255 | 256 | ['name','width','height','maxsize','units','resolution','defresolution'].forEach(function(prop) { 257 | assert.equal(map[prop], clone[prop], 'it should clone the map ' + prop); 258 | }); 259 | 260 | }); 261 | 262 | it('should get the map projection', function() { 263 | assert.doesNotThrow(function() { 264 | map = new mapserver.Map(mapfile); 265 | }, Error, 'loading a valid map file should not throw an error.'); 266 | 267 | assert.equal(map.projection.projString, "+init=epsg:4326", 'getting map projection string failed. Got ' + map.projection.projString); 268 | 269 | var epsg3857 = new mapserver.Projection("+init=epsg:3857"); 270 | var point = new mapserver.Point(10.5, 20); 271 | point.project(map.projection, epsg3857); 272 | var delta = Math.abs(point.x - 1168854.6533293733).toFixed(6); 273 | assert.equal(delta, 0, 'reprojected x was not correct, delta was ' + delta); 274 | delta = Math.abs(point.y - 2273030.926987688).toFixed(6); 275 | assert.equal(delta, 0, 'reprojected y was not correct, delta was ' + delta); 276 | 277 | }); 278 | 279 | it('should set the map projection', function() { 280 | assert.doesNotThrow(function() { 281 | map = new mapserver.Map(mapfile); 282 | }, Error, 'loading a valid map file should not throw an error.'); 283 | map.projection = "+init=epsg:3857"; 284 | assert.equal(map.projection.projString, "+init=epsg:3857", 'setting map projection string failed. Got ' + map.projection.projString); 285 | }); 286 | 287 | it('should get a layer projection', function() { 288 | assert.doesNotThrow(function() { 289 | map = new mapserver.Map(mapfile); 290 | }, Error, 'loading a valid map file should not throw an error.'); 291 | 292 | assert.equal(map.layers.prov_bound.projection.projString, "+init=epsg:4326", 'getting layer projection string failed. Got ' + map.layers.prov_bound.projection.projString); 293 | }); 294 | 295 | it('should set a layer projection', function() { 296 | assert.doesNotThrow(function() { 297 | map = new mapserver.Map(mapfile); 298 | }, Error, 'loading a valid map file should not throw an error.'); 299 | map.layers.prov_bound.projection = "+init=epsg:3857"; 300 | assert.equal(map.layers.prov_bound.projection.projString, "+init=epsg:3857", 'setting map projection string failed. Got ' + map.projection.projString); 301 | }); 302 | 303 | it('should set the map symbol set', function() { 304 | assert.doesNotThrow(function() { 305 | map = new mapserver.Map(mapfile); 306 | }, Error, 'loading a valid map file should not throw an error.'); 307 | map.setSymbolSet(symbolfile); 308 | assert.equal(map.setSymbolSet(symbolfile), 0, 'setting symbolset failed.'); 309 | }); 310 | 311 | it('should set the map extent', function() { 312 | assert.doesNotThrow(function() { 313 | map = new mapserver.Map(mapfile); 314 | }, Error, 'loading a valid map file should not throw an error.'); 315 | 316 | map.setExtent(-90, -45, 90, 45); 317 | assert.equal(map.extent.minx, -90, 'setting map extent minx failed'); 318 | assert.equal(map.extent.miny, -45, 'setting map extent miny failed'); 319 | assert.equal(map.extent.maxx, 90, 'setting map extent maxx failed'); 320 | assert.equal(map.extent.maxy, 45, 'setting map extent maxy failed'); 321 | 322 | map.extent.project(map.projection, new mapserver.Projection("+init=epsg:3857")); 323 | 324 | var delta = Math.abs(map.extent.minx + 10018754.171394622).toFixed(6); 325 | assert.equal(delta, 0, 'reprojecting map extent minx failed, delta was ' + delta); 326 | delta = Math.abs(map.extent.miny + 5621521.486192066).toFixed(6); 327 | assert.equal(delta, 0, 'reprojecting map extent miny failed, delta was ' + delta); 328 | delta = Math.abs(map.extent.maxx - 10018754.171394622).toFixed(6); 329 | assert.equal(delta, 0, 'reprojecting map extent maxx failed, delta was ' + delta); 330 | delta = Math.abs(map.extent.maxy - 5621521.486192066).toFixed(6); 331 | assert.equal(delta, 0, 'reprojecting map extent maxy failed, delta was ' + delta); 332 | 333 | }); 334 | 335 | it('should create a rect from the map extent', function() { 336 | assert.doesNotThrow(function() { 337 | map = new mapserver.Map(mapfile); 338 | }, Error, 'loading a valid map file should not throw an error.'); 339 | 340 | map.setExtent(-90, -45, 90, 45); 341 | 342 | var rect = new mapserver.Rect(map.extent); 343 | 344 | assert.equal(rect.minx, -90, 'rect does not match extent: minx failed'); 345 | assert.equal(rect.miny, -45, 'rect does not match extent: miny failed'); 346 | assert.equal(rect.maxx, 90, 'rect does not match extent: maxx failed'); 347 | assert.equal(rect.maxy, 45, 'rect does not match extent: maxy failed'); 348 | 349 | rect.minx = 0; 350 | assert.equal(map.extent.minx, -90, 'original rect should not be modified by copy modification'); 351 | assert.equal(rect.minx, 0, 'copied rect should be modified'); 352 | }); 353 | 354 | it('should compute cell size and scaledenom', function() { 355 | assert.doesNotThrow(function() { 356 | map = new mapserver.Map(mapfile); 357 | }, Error, 'loading a valid map file should not throw an error.'); 358 | // test effect of recompute on cellsize and scaledenom 359 | map.recompute(); 360 | var delta = Math.abs(map.cellsize - 0.6020066889632107).toFixed(6); 361 | assert.equal(delta, 0, 'recomputing map cellsize failed, got ' + map.cellsize); 362 | delta = Math.abs(map.scaledenom - 189621444.28093645).toFixed(6); 363 | assert.ok(delta, 0, 'recomputing map scaledenom failed, got '+ map.scaledemon); 364 | }); 365 | 366 | it('should have access to map layers', function() { 367 | assert.doesNotThrow(function() { 368 | map = new mapserver.Map(mapfile); 369 | }, Error, 'loading a valid map file should not throw an error.'); 370 | 371 | // test indexed accessor to map.layers 372 | assert.equal(map.layers.foo, undefined, 'map.layers should not expose arbitrary properties'); 373 | assert.equal(typeof map.layers.length, 'number', 'map.layers.length should be an integer'); 374 | assert.equal(map.layers.length, 3, 'map.layers.length should be 3'); 375 | 376 | // test accessor for layer name 377 | assert.notEqual(map.layers[1].name,'test', 'layer name should not be test before we change it'); 378 | map.layers[1].name = 'test'; 379 | assert.equal(map.layers[1].name, 'test', 'layer name should have changed.'); 380 | 381 | assert.equal(map.layers.prov_bound.connectiontype, mapserver.MS_SHAPEFILE, 'layer should have connectiontype MS_SHAPEFILE, got ' + map.layers.prov_bound.connectiontype); 382 | 383 | // layers should be accessible by name too 384 | assert.equal(map.layers['test'].name, 'test', 'layer should be accessible by name'); 385 | 386 | assert.equal(map.layers['test'].status, mapserver.MS_ON, 'layer status should be ON'); 387 | 388 | map.layers['test'].status = mapserver.MS_OFF; 389 | assert.equal(map.layers['test'].status, mapserver.MS_OFF, 'layer status should change to OFF'); 390 | //test accessor for layer connection string 391 | assert.equal(map.layers['test'].connection, undefined, 'layer should have no connection on init'); 392 | map.layers['test'].connection = 'myconnectionstring'; 393 | assert.equal(map.layers['test'].connection, 'myconnectionstring', 'layer should have correct connection string after set'); 394 | 395 | 396 | //should be able to replace layer with a valid string 397 | map.layers['test'].updateFromString('LAYER NAME "stringtest" TYPE LINE STATUS ON END'); 398 | assert.equal(map.layers[1].name, 'stringtest', 'layer updated from string should have new name'); 399 | assert.equal(map.layers['stringtest'].type, mapserver.MS_LAYER_LINE, 'layer updated from string should be type LINE'); 400 | assert.equal(map.layers['stringtest'].status, mapserver.MS_ON, 'layer updated from string should have status ON'); 401 | }); 402 | 403 | it('should create a new layer', function() { 404 | assert.doesNotThrow(function() { 405 | map = new mapserver.Map(mapfile); 406 | }, Error, 'loading a valid map file should not throw an error.'); 407 | 408 | assert.doesNotThrow(function() { 409 | layer = new mapserver.Layer('foo'); 410 | }, Error, 'constructing a layer should not throw an error.'); 411 | 412 | assert.ok(layer, 'layer should be an object'); 413 | assert.equal(layer.name, 'foo', 'new layer should have a name'); 414 | 415 | layer.name = 'bar'; 416 | assert.equal(layer.name, 'bar', 'should be able to set a name on a new layer'); 417 | 418 | assert.equal(layer.connectiontype, mapserver.MS_SHAPEFILE, 'layer should have connectiontype MS_SHAPEFILE'); 419 | 420 | map.insertLayer(layer); 421 | assert.equal(map.layers['bar'].name, 'bar', 'the new layer should have a name'); 422 | assert.equal(map.layers[map.layers.length-1].name, 'bar', 'the new layer should be at the end'); 423 | 424 | layer = new mapserver.Layer('first'); 425 | 426 | map.insertLayer(layer, 0); 427 | assert.equal(map.layers[0].name, 'first', 'the new layer should be at index 0'); 428 | 429 | layer = new mapserver.Layer('middle'); 430 | 431 | map.insertLayer(layer, 2); 432 | assert.equal(map.layers[2].name, 'middle', 'the new layer should be at index 2'); 433 | }); 434 | 435 | it('should get grid intersection coordinates', function() { 436 | assert.doesNotThrow(function() { 437 | map = new mapserver.Map(mapfile); 438 | }, Error, 'loading a valid map file should not throw an error.'); 439 | 440 | assert.equal(map.layers.grid.connectiontype, mapserver.MS_GRATICULE, 'grid layer should have connectiontype MS_GRATICULE'); 441 | 442 | var values = map.layers['grid'].getGridIntersectionCoordinates(); 443 | assert.ok(values, 'grid intersection result is not an object'); 444 | 445 | assert.ok(Array.isArray(values.left), 'left is not an array'); 446 | assert.ok(Array.isArray(values.top), 'top is not an array'); 447 | assert.ok(Array.isArray(values.right), 'right is not an array'); 448 | assert.ok(Array.isArray(values.bottom), 'bottom is not an array'); 449 | 450 | assert.equal(values.left.length, 15, 'does not have 15 values for the left array'); 451 | assert.equal(values.top.length, 15, 'does not have 15 values for the top array'); 452 | assert.equal(values.right.length, 15, 'does not have 15 values for the right array'); 453 | assert.equal(values.bottom.length, 15, 'does not have 15 values for the bottom array'); 454 | 455 | assert.equal(values.left[0].x, 0, 'first left value is not 0'); 456 | }); 457 | 458 | it('should have an output format', function() { 459 | assert.doesNotThrow(function() { 460 | map = new mapserver.Map(mapfile); 461 | }, Error, 'loading a valid map file should not throw an error.'); 462 | assert.equal(map.outputformat.name, 'png', 'output format name is incorrect'); 463 | assert.equal(map.outputformat.mimetype, 'image/png', 'output format mimetype is incorrect'); 464 | }); 465 | 466 | if (mapserver.getVersionInt() >= 60400) { 467 | it('should get layer and map metadata', function() { 468 | assert.doesNotThrow(function() { 469 | map = new mapserver.Map(mapfile); 470 | }, Error, 'loading a valid map file should not throw an error.'); 471 | 472 | assert.equal(map.metadata.foo, "bar", 'map should have metadata'); 473 | 474 | map.metadata.bar = 'foo'; 475 | assert.equal(map.metadata.bar, 'foo', 'should be able to set arbitrary metadata on the map'); 476 | 477 | assert.doesNotThrow(function() { 478 | layer = new mapserver.Layer('metalayer'); 479 | }, Error, 'constructing a layer should not throw an error.'); 480 | map.insertLayer(layer); 481 | 482 | assert.equal(map.layers['metalayer'].metadata['foo'], undefined, 'layer should have empty metadata on init'); 483 | 484 | map.layers['metalayer'].updateFromString('LAYER NAME "metatest" METADATA "foo" "bar" END END'); 485 | assert.equal(map.layers['metatest'].metadata['foo'], "bar", 'layer updated from string containing metadata should have metadata'); 486 | 487 | map.layers.metatest.metadata.foo = 'test'; 488 | assert.equal(map.layers.metatest.metadata.foo, 'test', 'should be able to set metadata on a layer'); 489 | 490 | map.layers.metatest.metadata.bar = 'foo'; 491 | assert.equal(map.layers.metatest.metadata.bar, 'foo', 'should be able to create arbitrary metadata'); 492 | 493 | }); 494 | } 495 | 496 | it('should get and set layer properties', function() { 497 | assert.doesNotThrow(function() { 498 | layer = new mapserver.Layer('foo'); 499 | }, Error, 'constructing a layer should not throw an error.'); 500 | 501 | assert.equal(layer.minscaledenom, -1, 'default minscaledenom value should be -1'); 502 | assert.equal(layer.maxscaledenom, -1, 'default maxscaledenom value should be -1'); 503 | assert.equal(layer.units, mapserver.MS_METERS, "default units for layer should be " + mapserver.MS_METERS + ", got " + layer.units); 504 | 505 | layer.minscaledenom = 10.1; 506 | assert.equal(layer.minscaledenom, 10.1, 'setting minscaledenom to float should work'); 507 | 508 | layer.minscaledenom = 9; 509 | assert.equal(layer.minscaledenom, 9, 'setting minscaledenom to int should work'); 510 | 511 | layer.minscaledenom = -1; 512 | assert.equal(layer.minscaledenom, -1, 'setting minscaledenom to -1 should work'); 513 | 514 | layer.maxscaledenom = 10.1; 515 | assert.equal(layer.maxscaledenom, 10.1, 'setting minscaledenom to float should work'); 516 | 517 | layer.maxscaledenom = 10; 518 | assert.equal(layer.maxscaledenom, 10, 'setting minscaledenom to int should work'); 519 | 520 | layer.maxscaledenom = -1; 521 | assert.equal(layer.maxscaledenom, -1, 'setting minscaledenom to -1 should work'); 522 | 523 | layer.units = mapserver.MS_DD; 524 | assert.equal(layer.units, mapserver.MS_DD, "setting layer units should work"); 525 | 526 | }); 527 | 528 | if (mapserver.getVersionInt() >= 60400) { 529 | it('should convert a layer to a string', function() { 530 | assert.doesNotThrow(function() { 531 | layer = new mapserver.Layer('foo'); 532 | }, Error, 'constructing a layer should not throw an error.'); 533 | 534 | var defaultLayerText = 'LAYER\n NAME "foo"\n STATUS OFF\n TILEITEM "location"\n UNITS METERS\nEND # LAYER\n\n'; 535 | 536 | assert.equal(layer.toString(), defaultLayerText, 'unexpected default layer text ' + layer.toString()); 537 | }); 538 | 539 | it('should be able to clone a layer using toString/updateFromString', function() { 540 | assert.doesNotThrow(function() { 541 | map = new mapserver.Map(mapfile); 542 | }, Error, 'loading a valid map file should not throw an error.'); 543 | 544 | var grid = map.layers.grid.toString(); 545 | 546 | var layer = new mapserver.Layer('grid2'); 547 | layer.updateFromString(grid); 548 | assert.equal(map.layers.grid.toString(), layer.toString(), 'updateFromString produced different results'); 549 | }); 550 | } 551 | 552 | it('should draw a map', function(done) { 553 | var v = mapserver.getVersionInt(); 554 | assert.doesNotThrow(function() { 555 | map = new mapserver.Map(mapfile); 556 | }, Error, 'loading a valid map file should not throw an error.'); 557 | fs.readFile(path.join(__dirname, 'data', 'test_buffer_'+v+'.png'), function(err, data) { 558 | map.drawMap(function(drawError, buffer) { 559 | if (drawError) { 560 | util.inspect(drawError, false, 0, true); 561 | assert.ok(false, 'Error drawing map.'); 562 | } else { 563 | fs.writeFileSync(path.join(__dirname, 'data', 'test_out_'+v+'.png'), buffer); 564 | if (err) { 565 | throw new Error('failed to load test image'); 566 | } 567 | assert.equal(data.toString('hex'), buffer.toString('hex'), 'map draw differed from sample image'); 568 | done(); 569 | } 570 | }); 571 | }); 572 | }); 573 | 574 | it('should get the label cache', function(done) { 575 | assert.doesNotThrow(function() { 576 | map = new mapserver.Map(mapfile); 577 | }, Error, 'loading a valid map file should not throw an error.'); 578 | 579 | map.setExtent(-150, 37, -50, 87); 580 | map.width = 1000; 581 | map.height = 600; 582 | 583 | var labels = map.getLabelCache(); 584 | assert.equal(labels.length, 0, 'Is not empty before drawing.'); 585 | map.drawMap(function(drawError) { 586 | if (drawError) { 587 | util.inspect(drawError, false, 0, true); 588 | assert.ok(false, 'Error drawing map.'); 589 | } else { 590 | labels = map.getLabelCache(); 591 | var numLabels = mapserver.getVersionInt() < 60500 ? 109 : 119; 592 | 593 | assert.equal(labels.length, numLabels, 'Does not have the right number of labels, expected (' + numLabels + ', got ' + labels.length); 594 | done(); 595 | } 596 | }); 597 | }); 598 | 599 | }); 600 | -------------------------------------------------------------------------------- /tests/tests copy.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Paul Spencer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | 18 | /*jshint node:true, sub:true */ 19 | /*global beforeEach, describe, it */ 20 | 21 | "use strict"; 22 | 23 | 24 | var assert = require('assert'); 25 | var util = require('util'); 26 | var mapserver = require('../mapserver'); 27 | var fs = require('fs'); 28 | var path = require('path'); 29 | var datadir = path.join(__dirname, 'data'); 30 | var mapfile = path.join(datadir, 'test.map'); 31 | var symbolfile = path.join(datadir, 'symbolset.txt'); 32 | var nomapfile = 'missing.map'; 33 | var map; 34 | var layer; 35 | var err; 36 | 37 | console.log('running tests for mapserver %s : %s', mapserver.getVersionInt(), mapserver.getVersion()); 38 | 39 | beforeEach(function() { 40 | mapserver.resetErrorList(); 41 | }); 42 | 43 | describe('mapserver', function() { 44 | it('should exports constants', function() { 45 | // test constants 46 | assert.equal(mapserver.MS_OFF, 0, 'MS_OFF not defined'); 47 | assert.equal(mapserver.MS_ON, 1, 'MS_ON not defined'); 48 | }); 49 | 50 | it('should get some basic info about mapserver', function() { 51 | assert.ok(mapserver.getVersionInt(), 'mapserver should report its version number'); 52 | assert.ok(mapserver.getVersion(), 'mapserver should report its version string'); 53 | assert.ok(mapserver.supportsThreads(), 'mapserver compiled without thread support.'); 54 | }); 55 | 56 | it('should have no errors yet', function() { 57 | // quick error test 58 | var err = mapserver.getError(); 59 | assert.equal(err.code, 0, 'should be no errors'); 60 | }); 61 | 62 | it('should create a projection', function() { 63 | // quick error test 64 | var proj = new mapserver.Projection("+init=epsg:4326"); 65 | assert.equal(proj.units, mapserver.MS_DD, 'projection units should be decimal degrees'); 66 | assert.equal(proj.projString, "+init=epsg:4326", 'getting projection string failed. Got ' + proj.projString); 67 | err = mapserver.getError(); 68 | assert.equal(err.code, 0, 'should be no errors'); 69 | proj.projString = "+init=epsg:3857"; 70 | assert.equal(proj.projString, "+init=epsg:3857", 'setting projection object via string failed. Got ' + proj.projString); 71 | }); 72 | 73 | it('should have a functional point object', function() { 74 | var point = new mapserver.Point(); 75 | assert.equal(point.x, -1, 'default point x should be -1'); 76 | assert.equal(point.y, -1, 'default point y should be -1'); 77 | 78 | point = new mapserver.Point(10.5, 20); 79 | assert.equal(point.x, 10.5, 'create a point with an x and y value'); 80 | assert.equal(point.y, 20, 'create a point with an x and y value'); 81 | 82 | var epsg4326 = new mapserver.Projection("+init=epsg:4326"); 83 | var epsg3857 = new mapserver.Projection("+init=epsg:3857"); 84 | point.project(epsg4326, epsg3857); 85 | 86 | var dx = Math.abs(point.x - 1168854.6533293733).toFixed(6); 87 | assert.equal(dx, 0, 'reprojected x was not correct, delta was ' + dx); 88 | var dy = Math.abs(point.y - 2273030.926987688).toFixed(6); 89 | assert.equal(dy, 0, 'reprojected y was not correct, delta was ' + dy); 90 | point = new mapserver.Point(0,0); 91 | assert.equal(point.distanceToPoint(new mapserver.Point(1,0)), 1, 'distanceToPoint should be 1'); 92 | }); 93 | 94 | it('should have a functional rect object', function() { 95 | var rect; 96 | 97 | assert.doesNotThrow(function() { 98 | rect = new mapserver.Rect(); 99 | }, 'creating a rect with 0 arguments should work.'); 100 | 101 | assert.equal(rect.minx, -1, 'default rect constructor minx should equal -1'); 102 | assert.equal(rect.miny, -1, 'default rect constructor miny should equal -1'); 103 | assert.equal(rect.maxx, -1, 'default rect constructor maxx should equal -1'); 104 | assert.equal(rect.maxy, -1, 'default rect constructor maxy should equal -1'); 105 | 106 | assert.doesNotThrow(function() { 107 | rect = new mapserver.Rect(1.2, 3.4, 5.6, 7.8); 108 | }, 'creating a rect with 4 arguments should work'); 109 | 110 | assert.equal(rect.minx, 1.2, 'rect minx should equal 1.2'); 111 | assert.equal(rect.miny, 3.4, 'rect miny should equal 3.4'); 112 | assert.equal(rect.maxx, 5.6, 'rect maxx should equal 5.6'); 113 | assert.equal(rect.maxy, 7.8, 'rect maxy should equal 7.8'); 114 | 115 | assert['throws'](function() { 116 | rect = new mapserver.Rect(1,1); 117 | }, Error, 'rect constructor should throw an error with wrong number of arguments.'); 118 | 119 | assert['throws'](function() { 120 | rect = new mapserver.Rect('a', 'b', 'c', 'd'); 121 | console.log(rect); 122 | }, Error, 'rect constructor should throw an error with wrong argument type.'); 123 | 124 | rect = new mapserver.Rect(3, 4, 1, 2); 125 | assert.equal(rect.minx, 1, 'rect minx should be minimum x value'); 126 | assert.equal(rect.miny, 2, 'rect miny should be minimum y value'); 127 | assert.equal(rect.maxx, 3, 'rect maxx should be maximum x value'); 128 | assert.equal(rect.maxy, 4, 'rect maxy should be maximum y value'); 129 | 130 | rect = new mapserver.Rect(); 131 | rect.minx = 1; 132 | rect.miny = 2; 133 | rect.maxx = 3; 134 | rect.maxy = 4; 135 | assert.equal(rect.minx, 1, 'rect minx should assignable'); 136 | assert.equal(rect.miny, 2, 'rect miny should assignable'); 137 | assert.equal(rect.maxx, 3, 'rect maxx should assignable'); 138 | assert.equal(rect.maxy, 4, 'rect maxy should assignable'); 139 | 140 | assert['throws'](function() { 141 | rect = new mapserver.Rect(0, 0, 1, 1); 142 | rect.project('a','b'); 143 | }, Error, 'rect project should throw an error with wrong argument type.'); 144 | rect = new mapserver.Rect(0, 0, 1, 1); 145 | rect.project(new mapserver.Projection('+init=epsg:4326'), new mapserver.Projection('+init=epsg:3857')); 146 | 147 | var delta = Math.abs(rect.minx - 0).toFixed(6); 148 | assert.equal(delta, 0, 'reprojecting rect minx failed, delta was ' + delta); 149 | delta = Math.abs(rect.miny - 0).toFixed(6); 150 | assert.equal(delta, 0, 'reprojecting rect miny failed, delta was ' + delta); 151 | delta = Math.abs(rect.maxx - 111319.49079327231).toFixed(6); 152 | assert.equal(delta, 0, 'reprojecting rect maxx failed, delta was ' + delta); 153 | delta = Math.abs(rect.maxy - 111325.14286638486).toFixed(6); 154 | assert.equal(delta, 0, 'reprojecting rect maxy failed, delta was ' + delta); 155 | }); 156 | 157 | it('should throw an error for a missing mapfile', function() { 158 | // Test default mapfile pattern (must end in .map) 159 | assert['throws'](function() { 160 | new mapserver.Map(nomapfile); 161 | }, Error, 'attempting to load a non-existent map should throw an error.'); 162 | 163 | // check error 164 | err = mapserver.getError(); 165 | assert.equal(err.code, 1, 'Missing map file error failed.'); 166 | 167 | // test resetErrorList 168 | mapserver.resetErrorList(); 169 | err = mapserver.getError(); 170 | assert.equal(err.code, 0, 'should be able to reset the error list'); 171 | }); 172 | 173 | it('should load a valid map file', function() { 174 | assert.doesNotThrow(function() { 175 | map = new mapserver.Map(mapfile, __dirname); 176 | }, function() { 177 | err = mapserver.getError(); 178 | console.log(util.inspect(err)); 179 | }, 'loading a valid map file with a data path should not throw an error.'); 180 | assert.equal(map.mappath, __dirname, 'map did not load with correct data directory'); 181 | 182 | assert.doesNotThrow(function() { 183 | map = new mapserver.Map(mapfile); 184 | }, function() { 185 | err = mapserver.getError(); 186 | console.log(util.inspect(err)); 187 | }, 'loading a valid map file with no data path should not throw an error.'); 188 | assert.equal(path.relative(map.mappath, path.dirname(mapfile)), '', 'map did not compute correct default data directory'); 189 | 190 | assert.doesNotThrow(function() { 191 | map = new mapserver.Map(); 192 | }, function() { 193 | err = mapserver.getError(); 194 | console.log(util.inspect(err)); 195 | }, 'creating a blank map should not throw an error'); 196 | }); 197 | 198 | it('should get basic information from the map object', function() { 199 | assert.doesNotThrow(function() { 200 | map = new mapserver.Map(mapfile); 201 | }, Error, 'loading a valid map file should not throw an error.'); 202 | 203 | assert.equal(map.name, "GMAP_DEMO", 'map name is incorrect'); 204 | assert.equal(map.status, mapserver.MS_ON, 'map status is not ON'); 205 | assert.equal(map.width, 600, 'getting map width failed'); 206 | assert.equal(map.height, 300, 'getting map height failed'); 207 | assert.equal(map.cellsize, 0, 'default map cellsize should be 0, got ' + map.cellsize); 208 | assert.equal(map.scaledenom, -1, 'default map scaledenom should be -1, got ' + map.scaledenom); 209 | assert.equal(map.maxsize, 2048, 'getting map maxsize failed'); 210 | assert.equal(map.units, mapserver.MS_DD, 'getting map units failed'); 211 | assert.equal(map.resolution, 72, 'getting map resolution failed'); 212 | assert.equal(map.defresolution, 72, 'getting map defresolution failed'); 213 | assert.equal(map.shapepath, './', 'getting shapepath failed'); 214 | assert.equal(map.imagetype, 'png', 'imagetype should be png, got ' + map.imagetype); 215 | assert.equal(map.mimetype, 'image/png', 'mimetype should be image/png, got ' + map.mimetype); 216 | }); 217 | 218 | it('should set map properties', function() { 219 | assert.doesNotThrow(function() { 220 | map = new mapserver.Map(mapfile); 221 | }, Error, 'loading a valid map file should not throw an error.'); 222 | 223 | // test setting map properties 224 | map.name = "test_set"; 225 | assert.equal(map.name, "test_set", "map name could not be set"); 226 | 227 | map.width = 600; 228 | assert.equal(map.width, 600, 'setting map width failed'); 229 | 230 | map.height = 600; 231 | assert.equal(map.height, 600, 'setting map height failed'); 232 | map.height = 300; 233 | assert.equal(map.height, 300, 'resetting map height failed'); 234 | 235 | map.maxsize = 4096; 236 | assert.equal(map.maxsize, 4096, 'setting map maxsize failed'); 237 | 238 | map.units = mapserver.MS_FEET; 239 | assert.equal(map.units, mapserver.MS_FEET, 'setting map units failed'); 240 | 241 | map.resolution = 96; 242 | assert.equal(map.resolution, 96, 'setting map defresolution failed'); 243 | 244 | map.defresolution = 96; 245 | assert.equal(map.defresolution, 96, 'setting map defresolution failed'); 246 | 247 | }); 248 | 249 | it('should clone a map object', function() { 250 | assert.doesNotThrow(function() { 251 | map = new mapserver.Map(mapfile); 252 | }, Error, 'loading a valid map file should not throw an error.'); 253 | 254 | var clone = map.clone(); 255 | 256 | ['name','width','height','maxsize','units','resolution','defresolution'].forEach(function(prop) { 257 | assert.equal(map[prop], clone[prop], 'it should clone the map ' + prop); 258 | }); 259 | 260 | }); 261 | 262 | it('should get the map projection', function() { 263 | assert.doesNotThrow(function() { 264 | map = new mapserver.Map(mapfile); 265 | }, Error, 'loading a valid map file should not throw an error.'); 266 | 267 | assert.equal(map.projection.projString, "+init=epsg:4326", 'getting map projection string failed. Got ' + map.projection.projString); 268 | 269 | var epsg3857 = new mapserver.Projection("+init=epsg:3857"); 270 | var point = new mapserver.Point(10.5, 20); 271 | point.project(map.projection, epsg3857); 272 | var delta = Math.abs(point.x - 1168854.6533293733).toFixed(6); 273 | assert.equal(delta, 0, 'reprojected x was not correct, delta was ' + delta); 274 | delta = Math.abs(point.y - 2273030.926987688).toFixed(6); 275 | assert.equal(delta, 0, 'reprojected y was not correct, delta was ' + delta); 276 | 277 | }); 278 | 279 | it('should set the map projection', function() { 280 | assert.doesNotThrow(function() { 281 | map = new mapserver.Map(mapfile); 282 | }, Error, 'loading a valid map file should not throw an error.'); 283 | map.projection = "+init=epsg:3857"; 284 | assert.equal(map.projection.projString, "+init=epsg:3857", 'setting map projection string failed. Got ' + map.projection.projString); 285 | }); 286 | 287 | it('should get a layer projection', function() { 288 | assert.doesNotThrow(function() { 289 | map = new mapserver.Map(mapfile); 290 | }, Error, 'loading a valid map file should not throw an error.'); 291 | 292 | assert.equal(map.layers.prov_bound.projection.projString, "+init=epsg:4326", 'getting layer projection string failed. Got ' + map.layers.prov_bound.projection.projString); 293 | }); 294 | 295 | it('should set a layer projection', function() { 296 | assert.doesNotThrow(function() { 297 | map = new mapserver.Map(mapfile); 298 | }, Error, 'loading a valid map file should not throw an error.'); 299 | map.layers.prov_bound.projection = "+init=epsg:3857"; 300 | assert.equal(map.layers.prov_bound.projection.projString, "+init=epsg:3857", 'setting map projection string failed. Got ' + map.projection.projString); 301 | }); 302 | 303 | it('should set the map symbol set', function() { 304 | assert.doesNotThrow(function() { 305 | map = new mapserver.Map(mapfile); 306 | }, Error, 'loading a valid map file should not throw an error.'); 307 | map.setSymbolSet(symbolfile); 308 | assert.equal(map.setSymbolSet(symbolfile), 0, 'setting symbolset failed.'); 309 | }); 310 | 311 | it('should set the map extent', function() { 312 | assert.doesNotThrow(function() { 313 | map = new mapserver.Map(mapfile); 314 | }, Error, 'loading a valid map file should not throw an error.'); 315 | 316 | map.setExtent(-90, -45, 90, 45); 317 | assert.equal(map.extent.minx, -90, 'setting map extent minx failed'); 318 | assert.equal(map.extent.miny, -45, 'setting map extent miny failed'); 319 | assert.equal(map.extent.maxx, 90, 'setting map extent maxx failed'); 320 | assert.equal(map.extent.maxy, 45, 'setting map extent maxy failed'); 321 | 322 | map.extent.project(map.projection, new mapserver.Projection("+init=epsg:3857")); 323 | 324 | var delta = Math.abs(map.extent.minx + 10018754.171394622).toFixed(6); 325 | assert.equal(delta, 0, 'reprojecting map extent minx failed, delta was ' + delta); 326 | delta = Math.abs(map.extent.miny + 5621521.486192066).toFixed(6); 327 | assert.equal(delta, 0, 'reprojecting map extent miny failed, delta was ' + delta); 328 | delta = Math.abs(map.extent.maxx - 10018754.171394622).toFixed(6); 329 | assert.equal(delta, 0, 'reprojecting map extent maxx failed, delta was ' + delta); 330 | delta = Math.abs(map.extent.maxy - 5621521.486192066).toFixed(6); 331 | assert.equal(delta, 0, 'reprojecting map extent maxy failed, delta was ' + delta); 332 | 333 | }); 334 | 335 | it('should create a rect from the map extent', function() { 336 | assert.doesNotThrow(function() { 337 | map = new mapserver.Map(mapfile); 338 | }, Error, 'loading a valid map file should not throw an error.'); 339 | 340 | map.setExtent(-90, -45, 90, 45); 341 | 342 | var rect = new mapserver.Rect(map.extent); 343 | 344 | assert.equal(rect.minx, -90, 'rect does not match extent: minx failed'); 345 | assert.equal(rect.miny, -45, 'rect does not match extent: miny failed'); 346 | assert.equal(rect.maxx, 90, 'rect does not match extent: maxx failed'); 347 | assert.equal(rect.maxy, 45, 'rect does not match extent: maxy failed'); 348 | 349 | rect.minx = 0; 350 | assert.equal(map.extent.minx, -90, 'original rect should not be modified by copy modification'); 351 | assert.equal(rect.minx, 0, 'copied rect should be modified'); 352 | }); 353 | 354 | it('should compute cell size and scaledenom', function() { 355 | assert.doesNotThrow(function() { 356 | map = new mapserver.Map(mapfile); 357 | }, Error, 'loading a valid map file should not throw an error.'); 358 | // test effect of recompute on cellsize and scaledenom 359 | map.recompute(); 360 | var delta = Math.abs(map.cellsize - 0.6020066889632107).toFixed(6); 361 | assert.equal(delta, 0, 'recomputing map cellsize failed, got ' + map.cellsize); 362 | delta = Math.abs(map.scaledenom - 189621444.28093645).toFixed(6); 363 | assert.ok(delta, 0, 'recomputing map scaledenom failed, got '+ map.scaledemon); 364 | }); 365 | 366 | it('should have access to map layers', function() { 367 | assert.doesNotThrow(function() { 368 | map = new mapserver.Map(mapfile); 369 | }, Error, 'loading a valid map file should not throw an error.'); 370 | 371 | // test indexed accessor to map.layers 372 | assert.equal(map.layers.foo, undefined, 'map.layers should not expose arbitrary properties'); 373 | assert.equal(typeof map.layers.length, 'number', 'map.layers.length should be an integer'); 374 | assert.equal(map.layers.length, 3, 'map.layers.length should be 3'); 375 | 376 | // test accessor for layer name 377 | assert.notEqual(map.layers[1].name,'test', 'layer name should not be test before we change it'); 378 | map.layers[1].name = 'test'; 379 | assert.equal(map.layers[1].name, 'test', 'layer name should have changed.'); 380 | 381 | console.log(map.layers.prov_bound.name); 382 | 383 | assert.equal(map.layers.prov_bound.connectiontype, mapserver.MS_SHAPEFILE, 'layer should have connectiontype MS_SHAPEFILE, got ' + map.layers.prov_bound.connectiontype); 384 | 385 | // layers should be accessible by name too 386 | assert.equal(map.layers['test'].name, 'test', 'layer should be accessible by name'); 387 | 388 | assert.equal(map.layers['test'].status, mapserver.MS_ON, 'layer status should be ON'); 389 | 390 | map.layers['test'].status = mapserver.MS_OFF; 391 | assert.equal(map.layers['test'].status, mapserver.MS_OFF, 'layer status should change to OFF'); 392 | //test accessor for layer connection string 393 | assert.equal(map.layers['test'].connection, undefined, 'layer should have no connection on init'); 394 | map.layers['test'].connection = 'myconnectionstring'; 395 | assert.equal(map.layers['test'].connection, 'myconnectionstring', 'layer should have correct connection string after set'); 396 | 397 | 398 | //should be able to replace layer with a valid string 399 | map.layers['test'].updateFromString('LAYER NAME "stringtest" TYPE LINE STATUS ON END'); 400 | assert.equal(map.layers[1].name, 'stringtest', 'layer updated from string should have new name'); 401 | assert.equal(map.layers['stringtest'].type, mapserver.MS_LAYER_LINE, 'layer updated from string should be type LINE'); 402 | assert.equal(map.layers['stringtest'].status, mapserver.MS_ON, 'layer updated from string should have status ON'); 403 | }); 404 | 405 | it('should create a new layer', function() { 406 | assert.doesNotThrow(function() { 407 | map = new mapserver.Map(mapfile); 408 | }, Error, 'loading a valid map file should not throw an error.'); 409 | 410 | assert.doesNotThrow(function() { 411 | layer = new mapserver.Layer('foo'); 412 | }, Error, 'constructing a layer should not throw an error.'); 413 | 414 | assert.ok(layer, 'layer should be an object'); 415 | assert.equal(layer.name, 'foo', 'new layer should have a name'); 416 | 417 | layer.name = 'bar'; 418 | assert.equal(layer.name, 'bar', 'should be able to set a name on a new layer'); 419 | 420 | assert.equal(layer.connectiontype, mapserver.MS_SHAPEFILE, 'layer should have connectiontype MS_SHAPEFILE'); 421 | 422 | map.insertLayer(layer); 423 | assert.equal(map.layers['bar'].name, 'bar', 'the new layer should have a name'); 424 | assert.equal(map.layers[map.layers.length-1].name, 'bar', 'the new layer should be at the end'); 425 | 426 | layer = new mapserver.Layer('first'); 427 | 428 | map.insertLayer(layer, 0); 429 | assert.equal(map.layers[0].name, 'first', 'the new layer should be at index 0'); 430 | 431 | layer = new mapserver.Layer('middle'); 432 | 433 | map.insertLayer(layer, 2); 434 | assert.equal(map.layers[2].name, 'middle', 'the new layer should be at index 2'); 435 | }); 436 | 437 | it('should get grid intersection coordinates', function() { 438 | assert.doesNotThrow(function() { 439 | map = new mapserver.Map(mapfile); 440 | }, Error, 'loading a valid map file should not throw an error.'); 441 | 442 | assert.equal(map.layers.grid.connectiontype, mapserver.MS_GRATICULE, 'grid layer should have connectiontype MS_GRATICULE'); 443 | 444 | var values = map.layers['grid'].getGridIntersectionCoordinates(); 445 | assert.ok(values, 'grid intersection result is not an object'); 446 | 447 | assert.ok(Array.isArray(values.left), 'left is not an array'); 448 | assert.ok(Array.isArray(values.top), 'top is not an array'); 449 | assert.ok(Array.isArray(values.right), 'right is not an array'); 450 | assert.ok(Array.isArray(values.bottom), 'bottom is not an array'); 451 | 452 | assert.equal(values.left.length, 15, 'does not have 15 values for the left array'); 453 | assert.equal(values.top.length, 15, 'does not have 15 values for the top array'); 454 | assert.equal(values.right.length, 15, 'does not have 15 values for the right array'); 455 | assert.equal(values.bottom.length, 15, 'does not have 15 values for the bottom array'); 456 | 457 | assert.equal(values.left[0].x, 0, 'first left value is not 0'); 458 | }); 459 | 460 | it('should have an output format', function() { 461 | assert.doesNotThrow(function() { 462 | map = new mapserver.Map(mapfile); 463 | }, Error, 'loading a valid map file should not throw an error.'); 464 | assert.equal(map.outputformat.name, 'png', 'output format name is incorrect'); 465 | assert.equal(map.outputformat.mimetype, 'image/png', 'output format mimetype is incorrect'); 466 | }); 467 | 468 | if (mapserver.getVersionInt() >= 60400) { 469 | it('should get layer and map metadata', function() { 470 | assert.doesNotThrow(function() { 471 | map = new mapserver.Map(mapfile); 472 | }, Error, 'loading a valid map file should not throw an error.'); 473 | 474 | assert.equal(map.metadata.foo, "bar", 'map should have metadata'); 475 | 476 | map.metadata.bar = 'foo'; 477 | assert.equal(map.metadata.bar, 'foo', 'should be able to set arbitrary metadata on the map'); 478 | 479 | assert.doesNotThrow(function() { 480 | layer = new mapserver.Layer('metalayer'); 481 | }, Error, 'constructing a layer should not throw an error.'); 482 | map.insertLayer(layer); 483 | 484 | assert.equal(map.layers['metalayer'].metadata['foo'], undefined, 'layer should have empty metadata on init'); 485 | 486 | map.layers['metalayer'].updateFromString('LAYER NAME "metatest" METADATA "foo" "bar" END END'); 487 | assert.equal(map.layers['metatest'].metadata['foo'], "bar", 'layer updated from string containing metadata should have metadata'); 488 | 489 | map.layers.metatest.metadata.foo = 'test'; 490 | assert.equal(map.layers.metatest.metadata.foo, 'test', 'should be able to set metadata on a layer'); 491 | 492 | map.layers.metatest.metadata.bar = 'foo'; 493 | assert.equal(map.layers.metatest.metadata.bar, 'foo', 'should be able to create arbitrary metadata'); 494 | 495 | }); 496 | } 497 | 498 | it('should get and set layer properties', function() { 499 | assert.doesNotThrow(function() { 500 | layer = new mapserver.Layer('foo'); 501 | }, Error, 'constructing a layer should not throw an error.'); 502 | 503 | assert.equal(layer.minscaledenom, -1, 'default minscaledenom value should be -1'); 504 | assert.equal(layer.maxscaledenom, -1, 'default maxscaledenom value should be -1'); 505 | assert.equal(layer.units, mapserver.MS_METERS, "default units for layer should be " + mapserver.MS_METERS + ", got " + layer.units); 506 | 507 | layer.minscaledenom = 10.1; 508 | assert.equal(layer.minscaledenom, 10.1, 'setting minscaledenom to float should work'); 509 | 510 | layer.minscaledenom = 9; 511 | assert.equal(layer.minscaledenom, 9, 'setting minscaledenom to int should work'); 512 | 513 | layer.minscaledenom = -1; 514 | assert.equal(layer.minscaledenom, -1, 'setting minscaledenom to -1 should work'); 515 | 516 | layer.maxscaledenom = 10.1; 517 | assert.equal(layer.maxscaledenom, 10.1, 'setting minscaledenom to float should work'); 518 | 519 | layer.maxscaledenom = 10; 520 | assert.equal(layer.maxscaledenom, 10, 'setting minscaledenom to int should work'); 521 | 522 | layer.maxscaledenom = -1; 523 | assert.equal(layer.maxscaledenom, -1, 'setting minscaledenom to -1 should work'); 524 | 525 | layer.units = mapserver.MS_DD; 526 | assert.equal(layer.units, mapserver.MS_DD, "setting layer units should work"); 527 | 528 | }); 529 | 530 | if (mapserver.getVersionInt() >= 60400) { 531 | it('should convert a layer to a string', function() { 532 | assert.doesNotThrow(function() { 533 | layer = new mapserver.Layer('foo'); 534 | }, Error, 'constructing a layer should not throw an error.'); 535 | 536 | var defaultLayerText = 'LAYER\n NAME "foo"\n STATUS OFF\n TILEITEM "location"\n UNITS METERS\nEND # LAYER\n\n'; 537 | 538 | assert.equal(layer.toString(), defaultLayerText, 'unexpected default layer text ' + layer.toString()); 539 | }); 540 | 541 | it('should be able to clone a layer using toString/updateFromString', function() { 542 | assert.doesNotThrow(function() { 543 | map = new mapserver.Map(mapfile); 544 | }, Error, 'loading a valid map file should not throw an error.'); 545 | 546 | var grid = map.layers.grid.toString(); 547 | 548 | var layer = new mapserver.Layer('grid2'); 549 | layer.updateFromString(grid); 550 | assert.equal(map.layers.grid.toString(), layer.toString(), 'updateFromString produced different results'); 551 | }); 552 | } 553 | 554 | it('should get the label cache', function(done) { 555 | assert.doesNotThrow(function() { 556 | map = new mapserver.Map(mapfile); 557 | }, Error, 'loading a valid map file should not throw an error.'); 558 | 559 | map.setExtent(-150, 37, -50, 87); 560 | map.width = 1000; 561 | map.height = 600; 562 | 563 | var labels = map.getLabelCache(); 564 | assert.equal(labels.length, 0, 'Is not empty before drawing.'); 565 | map.drawMap(function(drawError) { 566 | if (drawError) { 567 | util.inspect(drawError, false, 0, true); 568 | assert.ok(false, 'Error drawing map.'); 569 | } else { 570 | labels = map.getLabelCache(); 571 | var numLabels = mapserver.getVersionInt() < 60500 ? 109 : 119; 572 | 573 | assert.equal(labels.length, numLabels, 'Does not have the right number of labels, expected (' + numLabels + ', got ' + labels.length); 574 | done(); 575 | } 576 | }); 577 | }); 578 | 579 | it('should draw a map', function(done) { 580 | var v = mapserver.getVersionInt(); 581 | assert.doesNotThrow(function() { 582 | map = new mapserver.Map(mapfile); 583 | }, Error, 'loading a valid map file should not throw an error.'); 584 | fs.readFile(path.join(__dirname, 'data', 'test_buffer_'+v+'.png'), function(err, data) { 585 | map.drawMap(function(drawError, buffer) { 586 | if (drawError) { 587 | util.inspect(drawError, false, 0, true); 588 | assert.ok(false, 'Error drawing map.'); 589 | } else { 590 | fs.writeFileSync(path.join(__dirname, 'data', 'test_out_'+v+'.png'), buffer); 591 | if (err) { 592 | throw new Error('failed to load test image'); 593 | } 594 | assert.equal(data.toString('hex'), buffer.toString('hex'), 'map draw differed from sample image'); 595 | done(); 596 | } 597 | }); 598 | }); 599 | }); 600 | }); 601 | --------------------------------------------------------------------------------