Skip to content
This repository
Browse code

extent async isSolid to return pixel value - an integer for both imag…

…es and grids - beware 32 bit limits
  • Loading branch information...
commit fa1aee2590ca9432780d17fa325aed75c0e09f5e 1 parent 823ecff
Dane Springmeyer authored October 26, 2012
42  src/mapnik_grid_view.cpp
@@ -104,9 +104,11 @@ Handle<Value> GridView::height(const Arguments& args)
104 104
 typedef struct {
105 105
     uv_work_t request;
106 106
     GridView* g;
107  
-    std::string error_name;
108 107
     Persistent<Function> cb;
  108
+    bool error;
  109
+    std::string error_name;
109 110
     bool result;
  111
+    mapnik::grid_view::value_type pixel;
110 112
 } is_solid_grid_view_baton_t;
111 113
 
112 114
 
@@ -128,6 +130,8 @@ Handle<Value> GridView::isSolid(const Arguments& args)
128 130
     closure->request.data = closure;
129 131
     closure->g = g;
130 132
     closure->result = true;
  133
+    closure->pixel = 0;
  134
+    closure->error = false;
131 135
     closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
132 136
     uv_queue_work(uv_default_loop(), &closure->request, EIO_IsSolid, EIO_AfterIsSolid);
133 137
     g->Ref();
@@ -140,6 +144,7 @@ void GridView::EIO_IsSolid(uv_work_t* req)
140 144
     if (view->width() > 0 && view->height() > 0)
141 145
     {
142 146
         mapnik::grid_view::value_type first_pixel = view->getRow(0)[0];
  147
+        closure->pixel = first_pixel;
143 148
         for (unsigned y = 0; y < view->height(); ++y)
144 149
         {
145 150
             mapnik::grid_view::value_type const * row = view->getRow(y);
@@ -153,6 +158,11 @@ void GridView::EIO_IsSolid(uv_work_t* req)
153 158
             }
154 159
         }
155 160
     }
  161
+    else
  162
+    {
  163
+        closure->error = true;
  164
+        closure->error_name = "image does not have valid dimensions";
  165
+    }
156 166
 }
157 167
 
158 168
 void GridView::EIO_AfterIsSolid(uv_work_t* req)
@@ -160,8 +170,28 @@ void GridView::EIO_AfterIsSolid(uv_work_t* req)
160 170
     HandleScope scope;
161 171
     is_solid_grid_view_baton_t *closure = static_cast<is_solid_grid_view_baton_t *>(req->data);
162 172
     TryCatch try_catch;
163  
-    Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(Boolean::New(closure->result)) };
164  
-    closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  173
+    if (closure->error) {
  174
+        Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
  175
+        closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
  176
+    }
  177
+    else
  178
+    {
  179
+        if (closure->result)
  180
+        {
  181
+            Local<Value> argv[3] = { Local<Value>::New(Null()),
  182
+                                     Local<Value>::New(Boolean::New(closure->result)),
  183
+                                     Local<Value>::New(Number::New(closure->pixel)),
  184
+                                   };
  185
+            closure->cb->Call(Context::GetCurrent()->Global(), 3, argv);
  186
+        }
  187
+        else
  188
+        {
  189
+            Local<Value> argv[2] = { Local<Value>::New(Null()),
  190
+                                     Local<Value>::New(Boolean::New(closure->result))
  191
+                                   };
  192
+            closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  193
+        }
  194
+    }
165 195
     if (try_catch.HasCaught())
166 196
     {
167 197
         FatalException(try_catch);
@@ -439,8 +469,9 @@ void GridView::EIO_AfterEncode(uv_work_t* req)
439 469
     if (closure->error) {
440 470
         Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
441 471
         closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
442  
-    } else {
443  
-
  472
+    }
  473
+    else
  474
+    {
444 475
         // convert key order to proper javascript array
445 476
         Local<Array> keys_a = Array::New(closure->key_order.size());
446 477
         std::vector<std::string>::iterator it;
@@ -459,7 +490,6 @@ void GridView::EIO_AfterEncode(uv_work_t* req)
459 490
                                                            feature_data,
460 491
                                                            closure->key_order);
461 492
         }
462  
-
463 493
         // Create the return hash.
464 494
         Local<Object> json = Object::New();
465 495
         Local<Array> grid_array = Array::New(closure->lines.size());
42  src/mapnik_image_view.cpp
@@ -92,9 +92,11 @@ Handle<Value> ImageView::New(Image * JSImage ,
92 92
 typedef struct {
93 93
     uv_work_t request;
94 94
     ImageView* im;
95  
-    std::string error_name;
96 95
     Persistent<Function> cb;
  96
+    bool error;
  97
+    std::string error_name;
97 98
     bool result;
  99
+    mapnik::image_view<mapnik::image_data_32>::pixel_type pixel;
98 100
 } is_solid_image_view_baton_t;
99 101
 
100 102
 Handle<Value> ImageView::isSolid(const Arguments& args)
@@ -115,6 +117,8 @@ Handle<Value> ImageView::isSolid(const Arguments& args)
115 117
     closure->request.data = closure;
116 118
     closure->im = im;
117 119
     closure->result = true;
  120
+    closure->pixel = 0;
  121
+    closure->error = false;
118 122
     closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
119 123
     uv_queue_work(uv_default_loop(), &closure->request, EIO_IsSolid, EIO_AfterIsSolid);
120 124
     im->Ref();
@@ -127,11 +131,12 @@ void ImageView::EIO_IsSolid(uv_work_t* req)
127 131
     image_view_ptr view = closure->im->get();
128 132
     if (view->width() > 0 && view->height() > 0)
129 133
     {
130  
-        mapnik::image_view<mapnik::image_data_32>::pixel_type const* first_row = view->getRow(0);
131  
-        mapnik::image_view<mapnik::image_data_32>::pixel_type const first_pixel = first_row[0];
  134
+        typedef mapnik::image_view<mapnik::image_data_32>::pixel_type pixel_type;
  135
+        pixel_type const first_pixel = view->getRow(0)[0];
  136
+        closure->pixel = first_pixel;
132 137
         for (unsigned y = 0; y < view->height(); ++y)
133 138
         {
134  
-            mapnik::image_view<mapnik::image_data_32>::pixel_type const * row = view->getRow(y);
  139
+            pixel_type const * row = view->getRow(y);
135 140
             for (unsigned x = 0; x < view->width(); ++x)
136 141
             {
137 142
                 if (first_pixel != row[x])
@@ -142,6 +147,11 @@ void ImageView::EIO_IsSolid(uv_work_t* req)
142 147
             }
143 148
         }
144 149
     }
  150
+    else
  151
+    {
  152
+        closure->error = true;
  153
+        closure->error_name = "image does not have valid dimensions";
  154
+    }
145 155
 }
146 156
 
147 157
 void ImageView::EIO_AfterIsSolid(uv_work_t* req)
@@ -149,8 +159,28 @@ void ImageView::EIO_AfterIsSolid(uv_work_t* req)
149 159
     HandleScope scope;
150 160
     is_solid_image_view_baton_t *closure = static_cast<is_solid_image_view_baton_t *>(req->data);
151 161
     TryCatch try_catch;
152  
-    Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(Boolean::New(closure->result)) };
153  
-    closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  162
+    if (closure->error) {
  163
+        Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
  164
+        closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
  165
+    }
  166
+    else
  167
+    {
  168
+        if (closure->result)
  169
+        {
  170
+            Local<Value> argv[3] = { Local<Value>::New(Null()),
  171
+                                     Local<Value>::New(Boolean::New(closure->result)),
  172
+                                     Local<Value>::New(Number::New(closure->pixel)),
  173
+                                   };
  174
+            closure->cb->Call(Context::GetCurrent()->Global(), 3, argv);
  175
+        }
  176
+        else
  177
+        {
  178
+            Local<Value> argv[2] = { Local<Value>::New(Null()),
  179
+                                     Local<Value>::New(Boolean::New(closure->result))
  180
+                                   };
  181
+            closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  182
+        }
  183
+    }
154 184
     if (try_catch.HasCaught())
155 185
     {
156 186
         FatalException(try_catch);
12  test/grid_view.test.js
@@ -14,12 +14,14 @@ describe('mapnik.GridView ', function() {
14 14
     });
15 15
 
16 16
     it('should be solid', function() {
17  
-        assert.equal(view.isSolid(), true);
  17
+        assert.equal(view.isSolidSync(), true);
18 18
     });
19 19
 
20 20
     it('should be solid (async)', function(done) {
21  
-        view.isSolid(function(err,solid) {
  21
+        view.isSolid(function(err,solid,pixel) {
22 22
             assert.equal(solid, true);
  23
+            assert.equal(pixel, -2147483648);
  24
+            assert.equal(pixel, mapnik.Grid.base_mask);
23 25
             done();
24 26
         });
25 27
     });
@@ -30,6 +32,7 @@ describe('mapnik.GridView ', function() {
30 32
             assert.equal(pixel, 0);
31 33
         } else {
32 34
             assert.equal(pixel, -2147483648);
  35
+            assert.equal(pixel, mapnik.Grid.base_mask);
33 36
         }
34 37
     });
35 38
 
@@ -43,11 +46,12 @@ describe('mapnik.GridView ', function() {
43 46
         var grid = new mapnik.Grid(map.width, map.height, {key: '__id__'});
44 47
         map.render(grid, options, function(err, grid) {
45 48
             var view = grid.view(0, 0, 256, 256);
46  
-            assert.equal(view.isSolid(), false);
  49
+            assert.equal(view.isSolidSync(), false);
47 50
             // hit alaska (USA is id 207)
48 51
             assert.equal(view.getPixel(25, 100), 207);
49  
-            view.isSolid(function(err,solid){
  52
+            view.isSolid(function(err,solid,pixel){
50 53
                 assert.equal(solid, false);
  54
+                assert.equal(pixel, undefined);
51 55
                 done();
52 56
             });
53 57
         });
2  test/image.test.js
@@ -106,7 +106,7 @@ describe('mapnik.Image ', function() {
106 106
         gray.background = new mapnik.Color('white');
107 107
         gray.setGrayScaleToAlpha();
108 108
         var gray_view = gray.view(0, 0, gray.width(), gray.height());
109  
-        assert.equal(gray_view.isSolid(), true);
  109
+        assert.equal(gray_view.isSolidSync(), true);
110 110
         var pixel = gray_view.getPixel(0, 0);
111 111
         assert.equal(pixel.r, 255);
112 112
         assert.equal(pixel.g, 255);
33  test/image_view.test.js
@@ -18,7 +18,7 @@ describe('mapnik.ImageView ', function() {
18 18
     it('should be initialized properly', function() {
19 19
         var im = new mapnik.Image(256, 256);
20 20
         var view = im.view(0, 0, 256, 256);
21  
-        assert.equal(view.isSolid(), true);
  21
+        assert.equal(view.isSolidSync(), true);
22 22
         var pixel = view.getPixel(0, 0);
23 23
         assert.equal(pixel.r, 0);
24 24
         assert.equal(pixel.g, 0);
@@ -28,7 +28,7 @@ describe('mapnik.ImageView ', function() {
28 28
         im = new mapnik.Image(256, 256);
29 29
         im.background = new mapnik.Color(2, 2, 2, 2);
30 30
         view = im.view(0, 0, 256, 256);
31  
-        assert.equal(view.isSolid(), true);
  31
+        assert.equal(view.isSolidSync(), true);
32 32
         pixel = view.getPixel(0, 0);
33 33
         assert.equal(pixel.r, 2);
34 34
         assert.equal(pixel.g, 2);
@@ -40,9 +40,29 @@ describe('mapnik.ImageView ', function() {
40 40
     it('isSolid async works if true', function(done) {
41 41
         var im = new mapnik.Image(256, 256);
42 42
         var view = im.view(0, 0, 256, 256);
43  
-        assert.equal(view.isSolid(), true);
44  
-        view.isSolid(function(err,solid) {
  43
+        assert.equal(view.isSolidSync(), true);
  44
+        view.isSolid(function(err,solid,pixel) {
45 45
             assert.equal(solid, true);
  46
+            assert.equal(pixel, 0);
  47
+            done();
  48
+        });
  49
+    });
  50
+
  51
+    it('isSolid async works if true and white', function(done) {
  52
+        var im = new mapnik.Image(256, 256);
  53
+        var color = new mapnik.Color('white');
  54
+        im.background = color
  55
+        var view = im.view(0, 0, 256, 256);
  56
+        assert.equal(view.isSolidSync(), true);
  57
+        view.isSolid(function(err,solid,pixel) {
  58
+            assert.equal(solid, true);
  59
+            assert.equal(pixel, 4294967295);
  60
+            // NOTE: shifts are 32 bit signed ints in js, so creating the unsigned
  61
+            // rgba for white is not possible using normal bit ops
  62
+            // var rgba = (color.a << 24) | (color.b << 16) | (color.g << 8) | (color.r);
  63
+            // how about this? (from tilelive source)
  64
+            var rgba = color.a*(1<<24) + ((color.b<<16) | (color.g<<8) | color.r);
  65
+            assert.equal(pixel, rgba);
46 66
             done();
47 67
         });
48 68
     });
@@ -50,9 +70,10 @@ describe('mapnik.ImageView ', function() {
50 70
     it('isSolid async works if false', function(done) {
51 71
         var im = new mapnik.Image.open('./test/support/a.png');
52 72
         var view = im.view(0, 0, im.width(), im.height());
53  
-        assert.equal(view.isSolid(), false);
54  
-        view.isSolid(function(err,solid) {
  73
+        assert.equal(view.isSolidSync(), false);
  74
+        view.isSolid(function(err,solid,pixel) {
55 75
             assert.equal(solid, false);
  76
+            assert.equal(pixel, undefined);
56 77
             done();
57 78
         });
58 79
     });

0 notes on commit fa1aee2

Please sign in to comment.
Something went wrong with that request. Please try again.