// Vector Tile #define _USE_MATH_DEFINES #include // M_PI #include "vector_tile_config.hpp" // node-mapnik #include "mapnik_vector_tile.hpp" #include "mapnik_map.hpp" #include "mapnik_color.hpp" #include "mapnik_geometry.hpp" #include "mapnik_logger.hpp" #include "mapnik_feature.hpp" #include "mapnik_fonts.hpp" #include "mapnik_plugins.hpp" #include "mapnik_palette.hpp" #include "mapnik_projection.hpp" #include "mapnik_layer.hpp" #include "mapnik_datasource.hpp" #include "mapnik_featureset.hpp" #include "mapnik_image.hpp" #include "mapnik_image_view.hpp" #include "mapnik_cairo_surface.hpp" #if defined(GRID_RENDERER) #include "mapnik_grid.hpp" #include "mapnik_grid_view.hpp" #endif #include "mapnik_expression.hpp" #include "blend.hpp" // mapnik #include // for MAPNIK_DECL #include #include #include #include #include // boost #include // cairo #if defined(HAVE_CAIRO) #include #endif // std #include namespace node_mapnik { // napi property attributes napi_property_attributes const prop_attr = napi_writable; static std::string format_version(int version) { std::ostringstream s; s << version / 100000 << "." << version / 100 % 1000 << "." << version % 100; return s.str(); } static Napi::Value clearCache(Napi::CallbackInfo const& info) { Napi::Env env = info.Env(); #if defined(MAPNIK_MEMORY_MAPPED_FILE) mapnik::marker_cache::instance().clear(); mapnik::mapped_memory_cache::instance().clear(); #endif return env.Undefined(); } } // namespace node_mapnik /** * Mapnik is the core of cartographic design and processing. `node-mapnik` provides a * set of bindings to `mapnik` for node.js. * * ### Plugins * * Node Mapnik relies on a set of datasource input plugins that must be configured prior to using the API. * These plugins are either built into Mapnik, such as the "geojson" plugin * or rely on exeternal dependencies, such as GDAL. All plugin methods exist on the `mapnik` * class level. * * Plugins are referenced based on the location of the bindings on your system. These paths are generated * in the lib/binding/{build}/mapnik_settings.js file. These settings can be referenced by the `mapnik.settings` object. We recommend using the `require('path')` * object when building these paths: * * ``` * path.resolve(mapnik.settings.paths.input_plugins, 'geojson.input') * ``` * * @name mapnik * @class mapnik * @property {string} version current version of mapnik * @property {string} module_path path to native mapnik binding * @property {Object} supports indicates which of the following are supported: * grid, svg, cairo, cairo_pdf, cairo_svg, png, jpeg, tiff, webp, proj4, threadsafe * @property {Object} versions diagnostic object with versions of * node, v8, boost, boost_number, mapnik, mapnik_number, mapnik_git_describe, cairo * @property {Object} settings - object that defines local paths for particular plugins and addons. * * ``` * // mapnik.settings on OSX * { * paths: { * fonts: '/Users/username/mapnik/node_modules/mapnik/lib/binding/node-v46-darwin-x64/mapnik/fonts', * input_plugins: '/Users/username/mapnik/node_modules/mapnik/lib/binding/node-v46-darwin-x64/mapnik/input' * }, * env: { * ICU_DATA: '/Users/username/mapnik/node_modules/mapnik/lib/binding/node-v46-darwin-x64/share/mapnik/icu', * GDAL_DATA: '/Users/username/mapnik/node_modules/mapnik/lib/binding/node-v46-darwin-x64/share/mapnik/gdal', * PROJ_LIB: '/Users/username/mapnik/node_modules/mapnik/lib/binding/node-v46-darwin-x64/share/mapnik/proj' * } * } * ``` * @example * var mapnik = require('mapnik'); */ /** * Image type constants representing color and grayscale encodings. * Composite operation constants * * @property {number} clear * @property {number} src * @property {number} dst * @property {number} src_over * @property {number} dst_over * @property {number} src_in * @property {number} dst_in * @property {number} src_out * @property {number} dst_out * @property {number} src_atop * @property {number} dst_atop * @property {number} xor * @property {number} plus * @property {number} minus * @property {number} multiply * @property {number} screen * @property {number} overlay * @property {number} darken * @property {number} lighten * @property {number} color_dodge * @property {number} color_burn * @property {number} hard_light * @property {number} soft_light * @property {number} difference * @property {number} exclusion * @property {number} contrast * @property {number} invert * @property {number} invert-rgb * @property {number} grain_merge * @property {number} grain_extract * @property {number} hue * @property {number} saturation * @property {number} color * @property {number} linear_dodge * @property {number} linear_burn * @property {number} divide * @name compositeOp * @memberof mapnik * @static * @class */ void init_image_comp_op(Napi::Env env, Napi::Object exports) { Napi::Object composite_ops = Napi::Object::New(env); composite_ops.Set("clear", Napi::Number::New(env, mapnik::clear)); composite_ops.Set("src", Napi::Number::New(env, mapnik::src)); composite_ops.Set("dst", Napi::Number::New(env, mapnik::dst)); composite_ops.Set("src_over", Napi::Number::New(env, mapnik::src_over)); composite_ops.Set("dst_over", Napi::Number::New(env, mapnik::dst_over)); composite_ops.Set("src_in", Napi::Number::New(env, mapnik::src_in)); composite_ops.Set("dst_in", Napi::Number::New(env, mapnik::dst_in)); composite_ops.Set("src_out", Napi::Number::New(env, mapnik::src_out)); composite_ops.Set("dst_out", Napi::Number::New(env, mapnik::dst_out)); composite_ops.Set("src_atop", Napi::Number::New(env, mapnik::src_atop)); composite_ops.Set("dst_atop", Napi::Number::New(env, mapnik::dst_atop)); composite_ops.Set("xor", Napi::Number::New(env, mapnik::_xor)); composite_ops.Set("plus", Napi::Number::New(env, mapnik::plus)); composite_ops.Set("minus", Napi::Number::New(env, mapnik::minus)); composite_ops.Set("multiply", Napi::Number::New(env, mapnik::multiply)); composite_ops.Set("screen", Napi::Number::New(env, mapnik::screen)); composite_ops.Set("overlay", Napi::Number::New(env, mapnik::overlay)); composite_ops.Set("darken", Napi::Number::New(env, mapnik::darken)); composite_ops.Set("lighten", Napi::Number::New(env, mapnik::lighten)); composite_ops.Set("color_dodge", Napi::Number::New(env, mapnik::color_dodge)); composite_ops.Set("color_burn", Napi::Number::New(env, mapnik::color_burn)); composite_ops.Set("hard_light", Napi::Number::New(env, mapnik::hard_light)); composite_ops.Set("soft_light", Napi::Number::New(env, mapnik::soft_light)); composite_ops.Set("difference", Napi::Number::New(env, mapnik::difference)); composite_ops.Set("exclusion", Napi::Number::New(env, mapnik::exclusion)); composite_ops.Set("contrast", Napi::Number::New(env, mapnik::contrast)); composite_ops.Set("invert", Napi::Number::New(env, mapnik::invert)); composite_ops.Set("invert-rgb", Napi::Number::New(env, mapnik::invert_rgb)); composite_ops.Set("grain_merge", Napi::Number::New(env, mapnik::grain_merge)); composite_ops.Set("grain_extract", Napi::Number::New(env, mapnik::grain_extract)); composite_ops.Set("hue", Napi::Number::New(env, mapnik::hue)); composite_ops.Set("saturation", Napi::Number::New(env, mapnik::saturation)); composite_ops.Set("color", Napi::Number::New(env, mapnik::_color)); composite_ops.Set("linear_dodge", Napi::Number::New(env, mapnik::linear_dodge)); composite_ops.Set("linear_burn", Napi::Number::New(env, mapnik::linear_burn)); composite_ops.Set("divide", Napi::Number::New(env, mapnik::divide)); exports.Set("compositeOp", composite_ops); } /** * Image type constants representing color and grayscale encodings. * * @name imageType * @memberof mapnik * @static * @class * @property {number} rgba8 * @property {number} gray8 * @property {number} gray8s * @property {number} gray16 * @property {number} gray16s * @property {number} gray32 * @property {number} gray32s * @property {number} gray32f * @property {number} gray64 * @property {number} gray64s * @property {number} gray64f */ void init_image_types(Napi::Env env, Napi::Object exports) { Napi::Object image_types = Napi::Object::New(env); image_types.Set("null", Napi::Number::New(env, mapnik::image_dtype_null)); image_types.Set("rgba8", Napi::Number::New(env, mapnik::image_dtype_rgba8)); image_types.Set("gray8", Napi::Number::New(env, mapnik::image_dtype_gray8)); image_types.Set("gray8s", Napi::Number::New(env, mapnik::image_dtype_gray8s)); image_types.Set("gray16", Napi::Number::New(env, mapnik::image_dtype_gray16)); image_types.Set("gray16s", Napi::Number::New(env, mapnik::image_dtype_gray16s)); image_types.Set("gray32", Napi::Number::New(env, mapnik::image_dtype_gray32)); image_types.Set("gray32s", Napi::Number::New(env, mapnik::image_dtype_gray32s)); image_types.Set("gray32f", Napi::Number::New(env, mapnik::image_dtype_gray32f)); image_types.Set("gray64", Napi::Number::New(env, mapnik::image_dtype_gray64)); image_types.Set("gray64s", Napi::Number::New(env, mapnik::image_dtype_gray64s)); image_types.Set("gray64f", Napi::Number::New(env, mapnik::image_dtype_gray64f)); exports.Set("imageType", image_types); } /** * Image scaling type constants representing color and grayscale encodings. * * @name imageScaling * @memberof mapnik * @static * @class * @property {number} near * @property {number} bilinear * @property {number} bicubic * @property {number} spline16 * @property {number} spline36 * @property {number} hanning * @property {number} hamming * @property {number} hermite * @property {number} kaiser * @property {number} quadric * @property {number} catrom * @property {number} gaussian * @property {number} bessel * @property {number} mitchell * @property {number} sinc * @property {number} lanczos * @property {number} blackman */ void init_image_scalings(Napi::Env env, Napi::Object exports) { Napi::Object image_scaling_types = Napi::Object::New(env); image_scaling_types.Set("near", Napi::Number::New(env, mapnik::SCALING_NEAR)); image_scaling_types.Set("bilinear", Napi::Number::New(env, mapnik::SCALING_BILINEAR)); image_scaling_types.Set("bicubic", Napi::Number::New(env, mapnik::SCALING_BICUBIC)); image_scaling_types.Set("spline16", Napi::Number::New(env, mapnik::SCALING_SPLINE16)); image_scaling_types.Set("spline36", Napi::Number::New(env, mapnik::SCALING_SPLINE36)); image_scaling_types.Set("hanning", Napi::Number::New(env, mapnik::SCALING_HANNING)); image_scaling_types.Set("hamming", Napi::Number::New(env, mapnik::SCALING_HAMMING)); image_scaling_types.Set("hermite", Napi::Number::New(env, mapnik::SCALING_HERMITE)); image_scaling_types.Set("kaiser", Napi::Number::New(env, mapnik::SCALING_KAISER)); image_scaling_types.Set("quadric", Napi::Number::New(env, mapnik::SCALING_QUADRIC)); image_scaling_types.Set("catrom", Napi::Number::New(env, mapnik::SCALING_CATROM)); image_scaling_types.Set("gaussian", Napi::Number::New(env, mapnik::SCALING_GAUSSIAN)); image_scaling_types.Set("bessel", Napi::Number::New(env, mapnik::SCALING_BESSEL)); image_scaling_types.Set("mitchell", Napi::Number::New(env, mapnik::SCALING_MITCHELL)); image_scaling_types.Set("sinc", Napi::Number::New(env, mapnik::SCALING_SINC)); image_scaling_types.Set("lanczos", Napi::Number::New(env, mapnik::SCALING_LANCZOS)); image_scaling_types.Set("blackman", Napi::Number::New(env, mapnik::SCALING_BLACKMAN)); exports.Set("imageScaling", image_scaling_types); } /** * Constants representing fill types understood by [Clipper during vector tile encoding](http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm). * * @name polygonFillType * @memberof mapnik * @static * @class * @property {number} evenOdd * @property {number} nonZero * @property {number} positive * @property {number} negative */ void init_polygon_fill_types(Napi::Env env, Napi::Object exports) { Napi::Object polygon_fill_types = Napi::Object::New(env); polygon_fill_types.Set("evenOdd", Napi::Number::New(env, mapnik::vector_tile_impl::even_odd_fill)); polygon_fill_types.Set("nonZero", Napi::Number::New(env, mapnik::vector_tile_impl::non_zero_fill)); polygon_fill_types.Set("positive", Napi::Number::New(env, mapnik::vector_tile_impl::positive_fill)); polygon_fill_types.Set("negative", Napi::Number::New(env, mapnik::vector_tile_impl::negative_fill)); exports.Set("polygonFillType", polygon_fill_types); } /** * Constants representing `std::async` threading mode (aka [launch policy](http://en.cppreference.com/w/cpp/thread/launch)). * * @name threadingMode * @memberof mapnik * @static * @class * @property {number} async * @property {number} deferred */ void init_threading_mode_types(Napi::Env env, Napi::Object exports) { Napi::Object threading_mode_types = Napi::Object::New(env); threading_mode_types.Set("async", static_cast(std::launch::async)); threading_mode_types.Set("deferred", static_cast(std::launch::deferred)); threading_mode_types.Set("auto", static_cast(std::launch::async | std::launch::deferred)); exports.Set("threadingMode", threading_mode_types); } Napi::Object init(Napi::Env env, Napi::Object exports) { // methods exports.Set("registerDatasource", Napi::Function::New(env, node_mapnik::register_datasource)); exports.Set("register_datasource", Napi::Function::New(env, node_mapnik::register_datasource)); exports.Set("registerDatasources", Napi::Function::New(env, node_mapnik::register_datasources)); exports.Set("register_datasources", Napi::Function::New(env, node_mapnik::register_datasources)); exports.Set("datasources", Napi::Function::New(env, node_mapnik::available_input_plugins)); exports.Set("registerFonts", Napi::Function::New(env, node_mapnik::register_fonts)); exports.Set("register_fonts", Napi::Function::New(env, node_mapnik::register_fonts)); exports.Set("fonts", Napi::Function::New(env, node_mapnik::available_font_faces)); exports.Set("fontFiles", Napi::Function::New(env, node_mapnik::available_font_files)); exports.Set("memoryFonts", Napi::Function::New(env, node_mapnik::memory_fonts)); exports.Set("clearCache", Napi::Function::New(env, node_mapnik::clearCache)); exports.Set("blend", Napi::Function::New(env, node_mapnik::blend)); exports.Set("rgb2hsl", Napi::Function::New(env, node_mapnik::rgb2hsl)); exports.Set("hsl2rgb", Napi::Function::New(env, node_mapnik::hsl2rgb)); // classes Color::Initialize(env, exports, node_mapnik::prop_attr); Image::Initialize(env, exports, node_mapnik::prop_attr); ImageView::Initialize(env, exports, node_mapnik::prop_attr); Palette::Initialize(env, exports, node_mapnik::prop_attr); Datasource::Initialize(env, exports, node_mapnik::prop_attr); Projection::Initialize(env, exports, node_mapnik::prop_attr); ProjTransform::Initialize(env, exports, node_mapnik::prop_attr); Geometry::Initialize(env, exports, node_mapnik::prop_attr); Feature::Initialize(env, exports, node_mapnik::prop_attr); Featureset::Initialize(env, exports, node_mapnik::prop_attr); Layer::Initialize(env, exports, node_mapnik::prop_attr); Map::Initialize(env, exports, node_mapnik::prop_attr); Expression::Initialize(env, exports, node_mapnik::prop_attr); Logger::Initialize(env, exports, node_mapnik::prop_attr); CairoSurface::Initialize(env, exports, node_mapnik::prop_attr); #if defined(GRID_RENDERER) Grid::Initialize(env, exports, node_mapnik::prop_attr); GridView::Initialize(env, exports, node_mapnik::prop_attr); #endif VectorTile::Initialize(env, exports, node_mapnik::prop_attr); // enums init_image_types(env, exports); init_image_scalings(env, exports); init_image_comp_op(env, exports); init_polygon_fill_types(env, exports); init_threading_mode_types(env, exports); // versions // versions of deps Napi::Object versions = Napi::Object::New(env); versions.Set("boost", node_mapnik::format_version(BOOST_VERSION)); versions.Set("boost_number", BOOST_VERSION); versions.Set("mapnik", node_mapnik::format_version(MAPNIK_VERSION)); versions.Set("mapnik_number", MAPNIK_VERSION); versions.Set("mapnik_git_describe", MAPNIK_GIT_REVISION); #if defined(HAVE_CAIRO) versions.Set("cairo", CAIRO_VERSION_STRING); #endif exports.Set("versions", versions); // supports Napi::Object supports = Napi::Object::New(env); #ifdef GRID_RENDERER supports.Set("grid", Napi::Boolean::New(env, true)); #else supports.Set("grid", Napi::Boolean::New(env, false)); #endif #ifdef SVG_RENDERER supports.Set("svg", Napi::Boolean::New(env, true)); #else supports.Set("svg", Napi::Boolean::New(env, false)); #endif #if defined(HAVE_CAIRO) supports.Set("cairo", Napi::Boolean::New(env, true)); #ifdef CAIRO_HAS_PDF_SURFACE supports.Set("cairo_pdf", Napi::Boolean::New(env, true)); #else supports.Set("cairo_pdf", Napi::Boolean::New(env, false)); #endif #ifdef CAIRO_HAS_SVG_SURFACE supports.Set("cairo_svg", Napi::Boolean::New(env, true)); #else supports.Set("cairo_svg", Napi::Boolean::New(env, false)); #endif #else supports.Set("cairo", Napi::Boolean::New(env, false)); #endif #if defined(HAVE_PNG) supports.Set("png", Napi::Boolean::New(env, true)); #else supports.Set("png", Napi::Boolean::New(env, false)); #endif #if defined(HAVE_JPEG) supports.Set("jpeg", Napi::Boolean::New(env, true)); #else supports.Set("jpeg", Napi::Boolean::New(env, false)); #endif #if defined(HAVE_TIFF) supports.Set("tiff", Napi::Boolean::New(env, true)); #else supports.Set("tiff", Napi::Boolean::New(env, false)); #endif #if defined(HAVE_WEBP) supports.Set("webp", Napi::Boolean::New(env, true)); #else supports.Set("webp", Napi::Boolean::New(env, false)); #endif #if defined(MAPNIK_USE_PROJ4) supports.Set("proj4", Napi::Boolean::New(env, true)); #else supports.Set("proj4", Napi::Boolean::New(env, false)); #endif #if defined(MAPNIK_THREADSAFE) supports.Set("threadsafe", Napi::Boolean::New(env, true)); #else supports.Set("threadsafe", Napi::Boolean::New(env, false)); #endif exports.Set("supports", supports); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)