Skip to content

Commit

Permalink
image/grid sync/async clear methods - refs mapbox/tilelive-mapnik#50
Browse files Browse the repository at this point in the history
…- refs #93
  • Loading branch information
Dane Springmeyer committed Nov 12, 2012
1 parent 9f3aac2 commit d1ac323
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 12 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -53,9 +53,9 @@ For more sample code see 'examples/README.md'
* Node v0.6 or v0.8 * Node v0.6 or v0.8
* Mapnik 2.x * Mapnik 2.x


Mapnik 2.1.0 is targeted, but 2.0.x is also supported. Mapnik 2.2.x is targeted, but 2.1.x and 2.0.x is also supported.


This means that if you are running the Mapnik 2.1 series (current unreleased master) you must be running at least [0eddc2b5a0](https://github.com/mapnik/mapnik/commit/0eddc2b5a0d42fb1dcf5c228871eac145c089bbc). This means that if you are running the Mapnik 2.2 series (current unreleased master) you must be running at least [0eddc2b5a0](https://github.com/mapnik/mapnik/commit/eebc8cc73eb18903b07e3b3e0757c11925962124).


This means that if you are running the Mapnik 2.0.x series some minor test failures are expected: This means that if you are running the Mapnik 2.0.x series some minor test failures are expected:


Expand Down
89 changes: 88 additions & 1 deletion src/mapnik_grid.cpp
Expand Up @@ -35,12 +35,17 @@ void Grid::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor, "width", width); NODE_SET_PROTOTYPE_METHOD(constructor, "width", width);
NODE_SET_PROTOTYPE_METHOD(constructor, "height", height); NODE_SET_PROTOTYPE_METHOD(constructor, "height", height);
NODE_SET_PROTOTYPE_METHOD(constructor, "painted", painted); NODE_SET_PROTOTYPE_METHOD(constructor, "painted", painted);

NODE_SET_PROTOTYPE_METHOD(constructor, "clear", clear);
NODE_SET_PROTOTYPE_METHOD(constructor, "clearSync", clear);
// properties // properties
ATTR(constructor, "key", get_prop, set_prop); ATTR(constructor, "key", get_prop, set_prop);


target->Set(String::NewSymbol("Grid"),constructor->GetFunction()); target->Set(String::NewSymbol("Grid"),constructor->GetFunction());
#if MAPNIK_VERSION >= 200200
NODE_MAPNIK_DEFINE_CONSTANT(constructor->GetFunction(), "base_mask", mapnik::grid::base_mask); NODE_MAPNIK_DEFINE_CONSTANT(constructor->GetFunction(), "base_mask", mapnik::grid::base_mask);
#else
NODE_MAPNIK_DEFINE_CONSTANT(constructor->GetFunction(), "base_mask", 0);
#endif
} }


Grid::Grid(unsigned int width, unsigned int height, std::string const& key, unsigned int resolution) : Grid::Grid(unsigned int width, unsigned int height, std::string const& key, unsigned int resolution) :
Expand Down Expand Up @@ -122,6 +127,88 @@ Handle<Value> Grid::New(const Arguments& args)
return Undefined(); return Undefined();
} }


Handle<Value> Grid::clearSync(const Arguments& args)
{
HandleScope scope;
Grid* g = ObjectWrap::Unwrap<Grid>(args.This());
#if MAPNIK_VERSION >= 200200
g->get()->clear();
#endif
return Undefined();
}

typedef struct {
uv_work_t request;
Grid* g;
std::string format;
bool error;
std::string error_name;
Persistent<Function> cb;
} clear_grid_baton_t;

Handle<Value> Grid::clear(const Arguments& args)
{
HandleScope scope;
Grid* g = ObjectWrap::Unwrap<Grid>(args.This());

if (args.Length() == 0) {
return clearSync(args);
}
// ensure callback is a function
Local<Value> callback = args[args.Length()-1];
if (!args[args.Length()-1]->IsFunction())
return ThrowException(Exception::TypeError(
String::New("last argument must be a callback function")));
clear_grid_baton_t *closure = new clear_grid_baton_t();
closure->request.data = closure;
closure->g = g;
closure->error = false;
closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
uv_queue_work(uv_default_loop(), &closure->request, EIO_Clear, EIO_AfterClear);
g->Ref();
return Undefined();
}

void Grid::EIO_Clear(uv_work_t* req)
{
clear_grid_baton_t *closure = static_cast<clear_grid_baton_t *>(req->data);
try
{
#if MAPNIK_VERSION >= 200200
closure->g->get()->clear();
#endif
}
catch(std::exception const& ex)
{
closure->error = true;
closure->error_name = ex.what();
}
}

void Grid::EIO_AfterClear(uv_work_t* req)
{
HandleScope scope;
clear_grid_baton_t *closure = static_cast<clear_grid_baton_t *>(req->data);
TryCatch try_catch;
if (closure->error)
{
Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
}
else
{
Local<Value> argv[2] = { Local<Value>::New(Null()) };
closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
}
if (try_catch.HasCaught())
{
FatalException(try_catch);
}
closure->g->Unref();
closure->cb.Dispose();
delete closure;
}

Handle<Value> Grid::painted(const Arguments& args) Handle<Value> Grid::painted(const Arguments& args)
{ {
HandleScope scope; HandleScope scope;
Expand Down
4 changes: 4 additions & 0 deletions src/mapnik_grid.hpp
Expand Up @@ -28,6 +28,10 @@ class Grid: public node::ObjectWrap {
static Handle<Value> width(const Arguments &args); static Handle<Value> width(const Arguments &args);
static Handle<Value> height(const Arguments &args); static Handle<Value> height(const Arguments &args);
static Handle<Value> painted(const Arguments &args); static Handle<Value> painted(const Arguments &args);
static Handle<Value> clearSync(const Arguments& args);
static Handle<Value> clear(const Arguments& args);
static void EIO_Clear(uv_work_t* req);
static void EIO_AfterClear(uv_work_t* req);


static Handle<Value> get_prop(Local<String> property, static Handle<Value> get_prop(Local<String> property,
const AccessorInfo& info); const AccessorInfo& info);
Expand Down
92 changes: 83 additions & 9 deletions src/mapnik_image.cpp
Expand Up @@ -48,6 +48,7 @@ void Image::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor, "premultiply", premultiply); NODE_SET_PROTOTYPE_METHOD(constructor, "premultiply", premultiply);
NODE_SET_PROTOTYPE_METHOD(constructor, "demultiply", demultiply); NODE_SET_PROTOTYPE_METHOD(constructor, "demultiply", demultiply);
NODE_SET_PROTOTYPE_METHOD(constructor, "clear", clear); NODE_SET_PROTOTYPE_METHOD(constructor, "clear", clear);
NODE_SET_PROTOTYPE_METHOD(constructor, "clearSync", clear);


ATTR(constructor, "background", get_prop, set_prop); ATTR(constructor, "background", get_prop, set_prop);


Expand Down Expand Up @@ -149,6 +150,88 @@ void Image::set_prop(Local<String> property,
} }
} }


Handle<Value> Image::clearSync(const Arguments& args)
{
HandleScope scope;
Image* im = ObjectWrap::Unwrap<Image>(args.This());
#if MAPNIK_VERSION >= 200200
im->get()->clear();
#endif
return Undefined();
}

typedef struct {
uv_work_t request;
Image* im;
std::string format;
bool error;
std::string error_name;
Persistent<Function> cb;
} clear_image_baton_t;

Handle<Value> Image::clear(const Arguments& args)
{
HandleScope scope;
Image* im = ObjectWrap::Unwrap<Image>(args.This());

if (args.Length() == 0) {
return clearSync(args);
}
// ensure callback is a function
Local<Value> callback = args[args.Length()-1];
if (!args[args.Length()-1]->IsFunction())
return ThrowException(Exception::TypeError(
String::New("last argument must be a callback function")));
clear_image_baton_t *closure = new clear_image_baton_t();
closure->request.data = closure;
closure->im = im;
closure->error = false;
closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
uv_queue_work(uv_default_loop(), &closure->request, EIO_Clear, EIO_AfterClear);
im->Ref();
return Undefined();
}

void Image::EIO_Clear(uv_work_t* req)
{
clear_image_baton_t *closure = static_cast<clear_image_baton_t *>(req->data);
try
{
#if MAPNIK_VERSION >= 200200
closure->im->get()->clear();
#endif
}
catch(std::exception const& ex)
{
closure->error = true;
closure->error_name = ex.what();
}
}

void Image::EIO_AfterClear(uv_work_t* req)
{
HandleScope scope;
clear_image_baton_t *closure = static_cast<clear_image_baton_t *>(req->data);
TryCatch try_catch;
if (closure->error)
{
Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
}
else
{
Local<Value> argv[2] = { Local<Value>::New(Null()) };
closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
}
if (try_catch.HasCaught())
{
FatalException(try_catch);
}
closure->im->Unref();
closure->cb.Dispose();
delete closure;
}

Handle<Value> Image::setGrayScaleToAlpha(const Arguments& args) Handle<Value> Image::setGrayScaleToAlpha(const Arguments& args)
{ {
HandleScope scope; HandleScope scope;
Expand Down Expand Up @@ -194,15 +277,6 @@ Handle<Value> Image::setGrayScaleToAlpha(const Arguments& args)
return Undefined(); return Undefined();
} }


Handle<Value> Image::clear(const Arguments& args)
{
HandleScope scope;
Image* im = ObjectWrap::Unwrap<Image>(args.This());
mapnik::image_data_32 & data = im->this_->data();
std::memset(data.getData(),0,sizeof(mapnik::image_data_32::pixel_type)*data.width()*data.height());
return Undefined();
}

Handle<Value> Image::premultiply(const Arguments& args) Handle<Value> Image::premultiply(const Arguments& args)
{ {
HandleScope scope; HandleScope scope;
Expand Down
3 changes: 3 additions & 0 deletions src/mapnik_image.hpp
Expand Up @@ -33,7 +33,10 @@ class Image: public node::ObjectWrap {
static Handle<Value> composite(const Arguments &args); static Handle<Value> composite(const Arguments &args);
static Handle<Value> premultiply(const Arguments& args); static Handle<Value> premultiply(const Arguments& args);
static Handle<Value> demultiply(const Arguments& args); static Handle<Value> demultiply(const Arguments& args);
static Handle<Value> clearSync(const Arguments& args);
static Handle<Value> clear(const Arguments& args); static Handle<Value> clear(const Arguments& args);
static void EIO_Clear(uv_work_t* req);
static void EIO_AfterClear(uv_work_t* req);
static void EIO_Composite(uv_work_t* req); static void EIO_Composite(uv_work_t* req);
static void EIO_AfterComposite(uv_work_t* req); static void EIO_AfterComposite(uv_work_t* req);


Expand Down

0 comments on commit d1ac323

Please sign in to comment.