Add addImage, removeImage API (#7610)
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
"express": "^4.11.1",
|
||||
"lodash": "^4.16.4",
|
||||
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#49e8b407bdbbe6f7c92dbcb56d3d51f425fc2653",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#e714350e53da55be6ebbbee9e5a5512ae2b1630d",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#9ab19437e6a5272f1dfd7aaf12a7b5bbec208895",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-cmake": "^1.2.1",
|
||||
"pixelmatch": "^4.0.2",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <mbgl/style/conversion/source.hpp>
|
||||
#include <mbgl/style/conversion/layer.hpp>
|
||||
#include <mbgl/style/conversion/filter.hpp>
|
||||
#include <mbgl/sprite/sprite_image.cpp>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -58,6 +59,8 @@ void NodeMap::Init(v8::Local<v8::Object> target) {
|
||||
Nan::SetPrototypeMethod(tpl, "addSource", AddSource);
|
||||
Nan::SetPrototypeMethod(tpl, "addLayer", AddLayer);
|
||||
Nan::SetPrototypeMethod(tpl, "removeLayer", RemoveLayer);
|
||||
Nan::SetPrototypeMethod(tpl, "addImage", AddImage);
|
||||
Nan::SetPrototypeMethod(tpl, "removeImage", RemoveLayer);
|
||||
Nan::SetPrototypeMethod(tpl, "setLayoutProperty", SetLayoutProperty);
|
||||
Nan::SetPrototypeMethod(tpl, "setPaintProperty", SetPaintProperty);
|
||||
Nan::SetPrototypeMethod(tpl, "setFilter", SetFilter);
|
||||
@@ -579,6 +582,82 @@ void NodeMap::RemoveLayer(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
|
||||
nodeMap->map->removeLayer(*Nan::Utf8String(info[0]));
|
||||
}
|
||||
|
||||
void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
using namespace mbgl::style;
|
||||
using namespace mbgl::style::conversion;
|
||||
|
||||
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
|
||||
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
|
||||
|
||||
if (info.Length() != 3) {
|
||||
return Nan::ThrowTypeError("Three arguments required");
|
||||
}
|
||||
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowTypeError("First argument must be a string");
|
||||
}
|
||||
|
||||
if (!info[1]->IsObject()) {
|
||||
return Nan::ThrowTypeError("Second argument must be an object");
|
||||
}
|
||||
|
||||
if (!info[2]->IsObject()) {
|
||||
return Nan::ThrowTypeError("Third argument must be an object");
|
||||
}
|
||||
|
||||
auto optionObject = Nan::To<v8::Object>(info[2]).ToLocalChecked();
|
||||
|
||||
if (!Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
|
||||
return Nan::ThrowTypeError("height parameter required");
|
||||
}
|
||||
|
||||
if (!Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
|
||||
return Nan::ThrowTypeError("width parameter required");
|
||||
}
|
||||
|
||||
if (!Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()->IsUint32()) {
|
||||
return Nan::ThrowTypeError("pixelRatio parameter required");
|
||||
}
|
||||
|
||||
uint32_t imageHeight = Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()->Uint32Value();
|
||||
uint32_t imageWidth = Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()->Uint32Value();
|
||||
|
||||
if (imageWidth > 1024 || imageHeight > 1024) {
|
||||
return Nan::ThrowTypeError("Max height and width is 1024");
|
||||
}
|
||||
|
||||
uint32_t pixelRatio = Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()->Uint32Value();
|
||||
auto imageBuffer = Nan::To<v8::Object>(info[1]).ToLocalChecked()->ToObject();
|
||||
|
||||
if (node::Buffer::Length(imageBuffer) != imageHeight * imageWidth * 4) {
|
||||
return Nan::ThrowTypeError("Image size does not match buffer size");
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(node::Buffer::Length(imageBuffer));
|
||||
std::copy(node::Buffer::Data(imageBuffer), node::Buffer::Data(imageBuffer) + node::Buffer::Length(imageBuffer), data.get());
|
||||
mbgl::PremultipliedImage cPremultipliedImage({ imageWidth, imageHeight}, std::move(data));
|
||||
|
||||
nodeMap->map->addImage(*Nan::Utf8String(info[0]), std::make_unique<mbgl::SpriteImage>(std::move(cPremultipliedImage), pixelRatio));
|
||||
}
|
||||
|
||||
void NodeMap::RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
using namespace mbgl::style;
|
||||
using namespace mbgl::style::conversion;
|
||||
|
||||
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
|
||||
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
|
||||
|
||||
if (info.Length() != 1) {
|
||||
return Nan::ThrowTypeError("One argument required");
|
||||
}
|
||||
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowTypeError("First argument must be a string");
|
||||
}
|
||||
|
||||
nodeMap->map->removeImage(*Nan::Utf8String(info[0]));
|
||||
}
|
||||
|
||||
void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
using namespace mbgl::style;
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
static void AddSource(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void AddLayer(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void RemoveLayer(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void AddImage(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void SetPaintProperty(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
static void SetFilter(const Nan::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
@@ -111,6 +111,8 @@ test('Map', function(t) {
|
||||
'addSource',
|
||||
'addLayer',
|
||||
'removeLayer',
|
||||
'addImage',
|
||||
'removeImage',
|
||||
'setLayoutProperty',
|
||||
'setPaintProperty',
|
||||
'setFilter',
|
||||
@@ -129,6 +131,164 @@ test('Map', function(t) {
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('.addImage', function(t) {
|
||||
var options = {
|
||||
request: function() {},
|
||||
ratio: 1
|
||||
};
|
||||
|
||||
t.test('requires 3 arguments', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage();
|
||||
}, /Three arguments required/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires image argument to be an object', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', '', {});
|
||||
}, /Second argument must be an object/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires options argument to have a height param', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', {}, {
|
||||
width: 40,
|
||||
pixelRatio: 2
|
||||
});
|
||||
}, /height parameter required/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires options argument to have a pixelRatio param', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', {}, {
|
||||
width: 40,
|
||||
height: 40
|
||||
});
|
||||
}, /pixelRatio parameter required/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires specified height to be actual height of image', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', new Buffer(''), {
|
||||
width: 401,
|
||||
height: 400,
|
||||
pixelRatio: 1
|
||||
}, 'Image size does not match buffer size');
|
||||
});
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires height and width to be less than 1024', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', new Buffer(''), {
|
||||
width: 1025,
|
||||
height: 1025,
|
||||
pixelRatio: 1
|
||||
}, 'Max height and width is 1024');
|
||||
});
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
t.test('requires specified height to be actual height of image', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.addImage('foo', new Buffer(' '), {
|
||||
width: 401,
|
||||
height: 400,
|
||||
pixelRatio: 1
|
||||
}, 'Image size does not match buffer size');
|
||||
});
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('No error', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.doesNotThrow(function() {
|
||||
map.addImage('foo', new Buffer(' '), {
|
||||
width: 1,
|
||||
height: 1,
|
||||
pixelRatio: 1
|
||||
});
|
||||
});
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
t.test('.removeImage', function(t) {
|
||||
var options = {
|
||||
request: function() {},
|
||||
ratio: 1
|
||||
};
|
||||
|
||||
t.test('requires one argument', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.removeImage();
|
||||
}, /One argument required/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('requires string as first argument', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.throws(function() {
|
||||
map.removeImage({});
|
||||
}, /First argument must be a string/);
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('removes image', function(t) {
|
||||
var map = new mbgl.Map(options);
|
||||
|
||||
t.doesNotThrow(function() {
|
||||
map.removeImage('fooBar');
|
||||
});
|
||||
|
||||
map.release();
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
t.test('.load', function(t) {
|
||||
var options = {
|
||||
request: function() {},
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
var mbgl = require('../index');
|
||||
var request = require('request');
|
||||
var PNG = require('pngjs').PNG;
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
mbgl.on('message', function(msg) {
|
||||
console.log('%s (%s): %s', msg.severity, msg.class, msg.text);
|
||||
@@ -65,6 +68,16 @@ module.exports = function (style, options, callback) {
|
||||
applyOperations(operations.slice(1), callback);
|
||||
});
|
||||
|
||||
} else if (operation[0] === 'addImage') {
|
||||
var img = PNG.sync.read(fs.readFileSync(path.join(__dirname, '../../../node_modules', 'mapbox-gl-test-suite', operation[2])));
|
||||
|
||||
map.addImage(operation[1], img.data, {
|
||||
height: img.height,
|
||||
width: img.width,
|
||||
pixelRatio: 1
|
||||
});
|
||||
|
||||
applyOperations(operations.slice(1), callback);
|
||||
} else {
|
||||
// Ensure that the next `map.render(options)` does not overwrite this change.
|
||||
if (operation[0] === 'setCenter') {
|
||||
|
||||
Reference in New Issue
Block a user