Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: examples/graphics/life/life.cc

Issue 6286025: Port the Life example to Pepper 2. (Closed) Base URL: http://naclports.googlecode.com/svn/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
1 // Copyright 2010 The Native Client SDK Authors. All rights reserved. 1 // Copyright 2011 The Native Client SDK Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can 2 // Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file. 3 // be found in the LICENSE file.
4 4
5 #include <assert.h> 5 #include "examples/graphics/life/life.h"
6 #include <math.h> 6
7 #include <stdlib.h> 7 #include <ppapi/cpp/completion_callback.h>
8 #include <string.h> 8 #include <ppapi/cpp/var.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <cassert>
12 #include <cmath>
13 #include <cstdio>
14 #include <cstring>
11 #include <string> 15 #include <string>
12 16
13 #include <nacl/nacl_npapi.h>
14 #include <nacl/npapi_extensions.h>
15 #include <nacl/npupp.h>
16
17 #define JS_LOG(msg) \
18 const size_t line_number = __LINE__; \
19 size_t len = floor(line_number) + 1; \
20 len = std::string(msg).size() + strlen(__FILE__) + len + 5; \
21 char buffer[len]; \
22 memset(buffer, 0, len); \
23 snprintf(buffer, len, "%s:%i - ", __FILE__, line_number); \
24 strncat(buffer, std::string(msg).c_str(), len - strlen(buffer)); \
25 Log(npp_, buffer);
26
27 namespace { 17 namespace {
28 // Log given message to javascript console. 18 const char* const kUpdateMethodId = "update";
29 bool Log(NPP npp, const char* msg, ...) { 19 const char* const kAddCellAtPointMethodId = "addCellAtPoint";
30 bool rv = false;
31 NPObject* window = NULL;
32 if (NPERR_NO_ERROR == NPN_GetValue(npp, NPNVWindowNPObject, &window)) {
33 const char buffer[] = "top.console";
34 NPString console_stript = { 0 };
35 console_stript.UTF8Length = strlen(buffer);
36 console_stript.UTF8Characters = buffer;
37 NPVariant console;
38 if (NPN_Evaluate(npp, window, &console_stript, &console)) {
39 if (NPVARIANT_IS_OBJECT(console)) {
40 // Convert the message to NPString;
41 NPVariant text;
42 STRINGN_TO_NPVARIANT(msg, static_cast<uint32_t>(strlen(msg)),
43 text);
44 NPVariant result;
45 if (NPN_Invoke(npp, NPVARIANT_TO_OBJECT(console),
46 NPN_GetStringIdentifier("log"), &text, 1, &result)) {
47 NPN_ReleaseVariantValue(&result);
48 rv = true;
49 }
50 }
51 NPN_ReleaseVariantValue(&console);
52 }
53 }
54 return rv;
55 }
56
57 // seed for rand_r() - we only call rand_r from main thread.
58 static unsigned int gSeed = 0xC0DE533D;
59
60 // random number helper
61 // binary rand() returns 0 or 1
62 inline unsigned char brand() {
63 return static_cast<unsigned char>(rand_r(&gSeed) & 1);
64 }
65 20
66 inline uint32_t MakeRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { 21 inline uint32_t MakeRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
67 return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); 22 return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
68 } 23 }
69 24
70 void FlushCallback(NPP instance, NPDeviceContext* context, 25 // Map of neighboring colors.
71 NPError err, void* user_data) { 26 const uint32_t kNeighborColors[] = {
72 } 27 MakeRGBA(0x00, 0x00, 0x00, 0xff),
73 28 MakeRGBA(0x00, 0x40, 0x00, 0xff),
74 void* life(void* data); 29 MakeRGBA(0x00, 0x60, 0x00, 0xff),
75 30 MakeRGBA(0x00, 0x80, 0x00, 0xff),
76 // Life class holds information and functionality needed to render 31 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
77 // life into an Pepper 2D surface. 32 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
78 class Life : public NPObject { 33 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
79 public: 34 MakeRGBA(0x00, 0x00, 0x00, 0xff),
80 Life(NPP npp); 35 MakeRGBA(0x00, 0x40, 0x00, 0xff),
81 ~Life(); 36 MakeRGBA(0x00, 0x60, 0x00, 0xff),
82 NPError SetWindow(NPWindow* window); 37 MakeRGBA(0x00, 0x80, 0x00, 0xff),
83 void Update(); 38 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
84 void Plot(int x, int y); 39 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
85 void Stir(); 40 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
86 void Draw(); 41 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
87 void UpdateCells(); 42 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
88 void Swap(); 43 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
89 void HandleEvent(NPPepperEvent* event); 44 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
90
91 private:
92 void CreateContext();
93 void DestroyContext();
94 bool IsContextValid() {
95 return context2d_.region != NULL;
96 }
97 int width() const {
98 return width_;
99 }
100 int height() const {
101 return height_;
102 }
103 void* pixels() {
104 return context2d_.region;
105 }
106
107 NPP npp_;
108 NPExtensions* extensions_;
109 int width_, height_;
110 NPDevice* device2d_; // The PINPAPI 2D device.
111 NPDeviceContext2D context2d_; // The PINPAPI 2D drawing context.
112 bool scribble_;
113 bool quit_;
114 char *cell_in_;
115 char *cell_out_;
116 }; 45 };
117 46
118 Life::Life(NPP npp) : npp_(npp), extensions_(NULL), width_(0), height_(0), 47 // These represent the new health value of a cell based on its neighboring
119 device2d_(NULL), cell_in_(NULL), cell_out_(NULL) { 48 // values. The health is binary: either alive or dead.
120 memset(&context2d_, 0, sizeof(context2d_)); 49 const uint8_t kIsAlive[] = {
121 NPN_GetValue(npp_, NPNVPepperExtensions, &extensions_); 50 0, 0, 0, 1, 0, 0, 0, 0, // row for center cell dead
122 device2d_ = extensions_->acquireDevice(npp_, NPPepper2DDevice); 51 0, 0, 1, 1, 0, 0, 0, 0, // row for center cell alive
dmichael(do not use this one) 2011/02/03 20:08:44 This is still weird... the top row shows 0-7, the
David Springer 2011/02/03 21:09:47 I called out the middle value as special.
123 assert(extensions_); 52 0, 0
dmichael(do not use this one) 2011/02/03 20:08:44 You should only need 1 of these (total of 17 possi
David Springer 2011/02/03 21:09:47 Done.
53 };
54
55 void FlushCallback(void* data, int32_t result) {
56 static_cast<life::Life*>(data)->set_flush_pending(false);
57 }
58 } // namespace
59
60 namespace life {
61 Life::Life(PP_Instance instance) : pp::Instance(instance),
62 graphics_2d_context_(NULL),
63 pixel_buffer_(NULL),
64 flush_pending_(false),
65 cell_in_(NULL),
66 cell_out_(NULL) {
124 } 67 }
125 68
126 Life::~Life() { 69 Life::~Life() {
127 delete[] cell_in_; 70 delete[] cell_in_;
128 delete[] cell_out_; 71 delete[] cell_out_;
129 DestroyContext(); 72 DestroyContext();
73 delete pixel_buffer_;
130 } 74 }
131 75
132 void Life::CreateContext() { 76 pp::Var Life::GetInstanceObject() {
133 if (IsContextValid()) 77 LifeScriptObject* script_object = new LifeScriptObject(this);
134 return; 78 return pp::Var(this, script_object);
135 device2d_ = extensions_->acquireDevice(npp_, NPPepper2DDevice);
136 assert(device2d_);
137 NPDeviceContext2DConfig config;
138 NPError init_err = device2d_->initializeContext(npp_, &config, &context2d_);
139 assert(NPERR_NO_ERROR == init_err);
140 } 79 }
141 80
142 void Life::HandleEvent(NPPepperEvent* event) { 81 bool Life::Init(uint32_t argc, const char* argn[], const char* argv[]) {
143 bool plot = false; 82 return true;
144 if (event->type == NPEventType_MouseDown) {
145 scribble_ = true;
146 plot = true;
147 }
148 if (event->type == NPEventType_MouseUp) {
149 JS_LOG("MouseUp event");
150 scribble_ = false;
151 }
152 if (event->type == NPEventType_MouseMove) {
153 plot = scribble_;
154 }
155 if (plot) {
156 // place a blob of life
157 Plot(event->u.mouse.x - 1, event->u.mouse.y - 1);
158 Plot(event->u.mouse.x + 0, event->u.mouse.y - 1);
159 Plot(event->u.mouse.x + 1, event->u.mouse.y - 1);
160 Plot(event->u.mouse.x - 1, event->u.mouse.y + 0);
161 Plot(event->u.mouse.x + 0, event->u.mouse.y + 0);
162 Plot(event->u.mouse.x + 1, event->u.mouse.y + 0);
163 Plot(event->u.mouse.x - 1, event->u.mouse.y + 1);
164 Plot(event->u.mouse.x + 0, event->u.mouse.y + 1);
165 Plot(event->u.mouse.x + 1, event->u.mouse.y + 1);
166 }
167 }
168
169 void Life::DestroyContext() {
170 if (!IsContextValid())
171 return;
172 device2d_->destroyContext(npp_, &context2d_);
173 } 83 }
174 84
175 void Life::Plot(int x, int y) { 85 void Life::Plot(int x, int y) {
86 if (cell_in_ == NULL)
87 return;
176 if (x < 0) return; 88 if (x < 0) return;
177 if (x >= width()) return; 89 if (x >= width()) return;
178 if (y < 0) return; 90 if (y < 0) return;
179 if (y >= height()) return; 91 if (y >= height()) return;
180 *(cell_in_ + x + y * width()) = 1; 92 *(cell_in_ + x + y * width()) = 1;
181 } 93 }
182 94
183 NPError Life::SetWindow(NPWindow* window) { 95 void Life::DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
184 if (!window) 96 if (position.size().width() == width() &&
185 return NPERR_NO_ERROR; 97 position.size().height() == height())
186 width_ = window->width; 98 return; // Size didn't change, no need to update anything.
187 height_ = window->height;
188 if (!IsContextValid())
189 CreateContext();
190 99
191 const size_t size = width() * height(); 100 // Create a new device context with the new size.
101 DestroyContext();
102 CreateContext(position.size());
103 // Delete the old pixel buffer and create a new one.
104 delete pixel_buffer_;
192 delete[] cell_in_; 105 delete[] cell_in_;
193 delete[] cell_out_; 106 delete[] cell_out_;
194 cell_in_ = new char[size]; 107 pixel_buffer_ = NULL;
195 cell_out_ = new char[size]; 108 cell_in_ = cell_out_ = NULL;
196 std::fill(cell_in_, cell_in_ + size, 0); 109 if (graphics_2d_context_ != NULL) {
197 std::fill(cell_out_, cell_out_ + size, 0); 110 pixel_buffer_ = new pp::ImageData(this,
198 111 PP_IMAGEDATAFORMAT_BGRA_PREMUL,
199 NPDeviceFlushContextCallbackPtr callback = 112 graphics_2d_context_->size(),
200 reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); 113 false);
201 device2d_->flushContext(npp_, &context2d_, callback, NULL); 114 const size_t size = width() * height();
202 return NPERR_NO_ERROR; 115 cell_in_ = new uint8_t[size];
116 cell_out_ = new uint8_t[size];
117 std::fill(cell_in_, cell_in_ + size, 0);
118 std::fill(cell_out_, cell_out_ + size, 0);
119 }
203 } 120 }
204 121
205 void Life::Update() { 122 void Life::Update() {
206 Stir(); 123 Stir();
207 UpdateCells(); 124 UpdateCells();
208 Swap(); 125 Swap();
209 NPDeviceFlushContextCallbackPtr callback = 126 FlushPixelBuffer();
210 reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); 127 }
211 device2d_->flushContext(npp_, &context2d_, callback, NULL); 128
129 void Life::AddCellAtPoint(const pp::Var& var_x, const pp::Var& var_y) {
130 if (!var_x.is_number() || !var_y.is_number())
131 return;
132 int32_t x, y;
133 x = var_x.is_int() ? var_x.AsInt() : static_cast<int32_t>(var_x.AsDouble());
134 y = var_y.is_int() ? var_y.AsInt() : static_cast<int32_t>(var_y.AsDouble());
135 Plot(x - 1, y - 1);
136 Plot(x + 0, y - 1);
137 Plot(x + 1, y - 1);
138 Plot(x - 1, y + 0);
139 Plot(x + 0, y + 0);
140 Plot(x + 1, y + 0);
141 Plot(x - 1, y + 1);
142 Plot(x + 0, y + 1);
143 Plot(x + 1, y + 1);
212 } 144 }
213 145
214 void Life::Stir() { 146 void Life::Stir() {
147 if (cell_in_ == NULL || cell_out_ == NULL)
148 return;
215 const int height = this->height(); 149 const int height = this->height();
216 const int width = this->width(); 150 const int width = this->width();
217 for (int i = 0; i < width; ++i) { 151 for (int i = 0; i < width; ++i) {
218 cell_in_[i] = brand(); 152 cell_in_[i] = random_bits_.value();
219 cell_in_[i + (height - 1) * width] = brand(); 153 cell_in_[i + (height - 1) * width] = random_bits_.value();
220 } 154 }
221 for (int i = 0; i < height; ++i) { 155 for (int i = 0; i < height; ++i) {
222 cell_in_[i * width] = brand(); 156 cell_in_[i * width] = random_bits_.value();
223 cell_in_[i * width + (width - 2)] = brand(); 157 cell_in_[i * width + (width - 2)] = random_bits_.value();
nfullagar 2011/02/03 21:18:58 should above be i * width + (width - 1) ?
David Springer 2011/02/03 22:04:55 Done.
224 } 158 }
225 } 159 }
226 160
227 void Life::UpdateCells() { 161 void Life::UpdateCells() {
228 // map neighbor count to color 162 if (cell_in_ == NULL || cell_out_ == NULL || pixels() == NULL)
229 static unsigned int colors[18] = { 163 return;
230 MakeRGBA(0x00, 0x00, 0x00, 0xff),
231 MakeRGBA(0x00, 0x40, 0x00, 0xff),
232 MakeRGBA(0x00, 0x60, 0x00, 0xff),
233 MakeRGBA(0x00, 0x80, 0x00, 0xff),
234 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
235 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
236 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
237 MakeRGBA(0x00, 0x00, 0x00, 0xff),
238 MakeRGBA(0x00, 0x40, 0x00, 0xff),
239 MakeRGBA(0x00, 0x60, 0x00, 0xff),
240 MakeRGBA(0x00, 0x80, 0x00, 0xff),
241 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
242 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
243 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
244 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
245 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
246 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
247 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
248 };
249 // map neighbor count to alive/dead
250 static char replace[18] = {
251 0, 0, 0, 1, 0, 0, 0, 0, // row for center cell dead
252 0, 0, 1, 1, 0, 0, 0, 0, // row for center cell alive
253 };
254 const int height = this->height(); 164 const int height = this->height();
255 const int width = this->width(); 165 const int width = this->width();
256 // do neighbor sumation; apply rules, output pixel color 166 // Do neighbor sumation; apply rules, output pixel color.
257 for (int y = 1; y < (height - 1); ++y) { 167 for (int y = 1; y < (height - 1); ++y) {
258 char *src0 = cell_in_ + (y - 1) * width; 168 uint8_t *src0 = cell_in_ + (y - 1) * width;
259 char *src1 = cell_in_ + (y) * width; 169 uint8_t *src1 = cell_in_ + (y) * width;
260 char *src2 = cell_in_ + (y + 1) * width; 170 uint8_t *src2 = cell_in_ + (y + 1) * width;
261 int count; 171 int count;
262 unsigned int color; 172 uint32_t color;
263 char *dst = cell_out_ + (y) * width; 173 uint8_t *dst = cell_out_ + (y) * width;
264 uint32_t *pixels = static_cast<uint32_t*>(this->pixels()) + y * width; 174 uint32_t *pixel_buffer = pixels() + y * width;
265 for (int x = 1; x < (width - 1); ++x) { 175 for (int x = 1; x < (width - 1); ++x) {
nfullagar 2011/02/03 21:18:58 should ++src0, ++src, ++src2; be moved up here (or
David Springer 2011/02/03 22:04:55 Fixed by adding 1 to src0 above and starting the w
266 // build sum, weight center by 8x 176 // Build sum, weight center by 8x. Note that an alive center with all
177 // dead neighbors produces the same result as a dead center with all
178 // alive neighbors.
267 count = src0[-1] + src0[0] + src0[1] + 179 count = src0[-1] + src0[0] + src0[1] +
268 src1[-1] + src1[0] * 8 + src1[1] + 180 src1[-1] + src1[0] * 8 + src1[1] +
269 src2[-1] + src2[0] + src2[1]; 181 src2[-1] + src2[0] + src2[1];
270 color = colors[count]; 182 color = kNeighborColors[count];
271 *pixels++ = color; 183 *pixel_buffer++ = color;
272 *dst++ = replace[count]; 184 *dst++ = kIsAlive[count];
273 ++src0, ++src1, ++src2; 185 ++src0, ++src1, ++src2;
274 } 186 }
275 } 187 }
276 } 188 }
277 189
278 void Life::Swap() { 190 void Life::Swap() {
279 char* tmp = cell_in_; 191 uint8_t* tmp = cell_in_;
280 cell_in_ = cell_out_; 192 cell_in_ = cell_out_;
281 cell_out_ = tmp; 193 cell_out_ = tmp;
282 } 194 }
283 195
284 extern "C" { 196 void Life::CreateContext(const pp::Size& size) {
285 197 if (IsContextValid())
286 // The following functions implement functions to be used with npruntime. 198 return;
287 static NPObject* AllocateLife(NPP npp, NPClass* npclass) { 199 graphics_2d_context_ = new pp::Graphics2D(this, size, false);
288 Life* rv = new Life(npp); 200 if (!BindGraphics(*graphics_2d_context_)) {
289 return rv; 201 printf("Couldn't bind the device context\n");
202 }
290 } 203 }
291 204
292 static void Deallocate(NPObject* obj) { 205 void Life::DestroyContext() {
293 Life* const life = static_cast<Life*>(obj); 206 if (!IsContextValid())
294 delete life; 207 return;
208 delete graphics_2d_context_;
209 graphics_2d_context_ = NULL;
295 } 210 }
296 211
297 // These are for npruntime. 212 void Life::FlushPixelBuffer() {
298 static void Invalidate(NPObject*) { 213 if (!IsContextValid())
214 return;
215 graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point());
216 if (flush_pending())
217 return;
218 set_flush_pending(true);
219 graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this));
299 } 220 }
300 221
301 static bool HasMethod(NPObject*, NPIdentifier name) { 222 bool Life::LifeScriptObject::HasMethod(
302 bool rv = false; 223 const pp::Var& method,
303 NPUTF8* method_name = NPN_UTF8FromIdentifier(name); 224 pp::Var* exception) {
304 if (0 == memcmp(method_name, "update", sizeof("update"))) { 225 if (!method.is_string()) {
305 rv = true; 226 return false;
306 } 227 }
307 NPN_MemFree(method_name); 228 std::string method_name = method.AsString();
308 return rv; 229 return method_name == kUpdateMethodId ||
230 method_name == kAddCellAtPointMethodId;
309 } 231 }
310 232
311 static bool Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, 233 pp::Var Life::LifeScriptObject::Call(
312 uint32_t argc, NPVariant *result) { 234 const pp::Var& method,
313 bool rv = false; 235 const std::vector<pp::Var>& args,
314 NPUTF8* method_name = NPN_UTF8FromIdentifier(name); 236 pp::Var* exception) {
315 if (0 == memcmp(method_name, "update", sizeof("update"))) { 237 if (!method.is_string()) {
316 rv = true; 238 return pp::Var(false);
317 Life* const life = static_cast<Life*>(obj);
318 life->Update();
319 } 239 }
320 NPN_MemFree(method_name); 240 std::string method_name = method.AsString();
321 return rv; 241 if (app_instance_ != NULL) {
242 if (method_name == kUpdateMethodId) {
243 app_instance_->Update();
244 } else if (method_name == kAddCellAtPointMethodId) {
245 // Pull off the first two params.
246 if (args.size() < 2)
247 return pp::Var(false);
248 app_instance_->AddCellAtPoint(args[0], args[1]);
249 }
250 }
251 return pp::Var();
322 } 252 }
323 253
324 static bool InvokeDefault(NPObject *npobj, const NPVariant *args, 254 const uint32_t Life::RandomBitGenerator::kInitialRandSeed = 0xC0DE533D;
325 uint32_t argCount, NPVariant *result) { 255
326 return false; 256 uint8_t Life::RandomBitGenerator::value() {
257 return static_cast<uint32_t>(rand_r(&random_bit_seed_) & 1);
327 } 258 }
328 259
329 static bool HasProperty(NPObject *npobj, NPIdentifier name) { 260 } // namespace life
330 return false;
331 }
332 261
333 static bool GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) {
334 return false;
335 }
336
337 static bool SetProperty(NPObject *npobj, NPIdentifier name,
338 const NPVariant *value) {
339 return false;
340 }
341
342 static bool RemoveProperty(NPObject *npobj, NPIdentifier name) {
343 return false;
344 }
345
346 NPClass np_class = {
347 NP_CLASS_STRUCT_VERSION,
348 AllocateLife,
349 Deallocate,
350 Invalidate,
351 HasMethod,
352 Invoke,
353 InvokeDefault,
354 HasProperty,
355 GetProperty,
356 SetProperty,
357 RemoveProperty
358 };
359
360 // These functions are required by both the develop and publish versions,
361 // they are called when a module instance is first loaded, and when the module
362 // instance is finally deleted. They must use C-style linkage.
363 NPError NPP_Destroy(NPP instance, NPSavedData** save) {
364 if (instance == NULL) {
365 return NPERR_INVALID_INSTANCE_ERROR;
366 }
367
368 Life* life = static_cast<Life*>(instance->pdata);
369 if (life != NULL) {
370 NPN_ReleaseObject(life);
371 }
372 return NPERR_NO_ERROR;
373 }
374
375 // NPP_GetScriptableInstance retruns the NPObject pointer that corresponds to
376 // NPPVpluginScriptableNPObject queried by NPP_GetValue() from the browser.
377 NPObject* NPP_GetScriptableInstance(NPP instance) {
378 if (instance == NULL) {
379 return NULL;
380 }
381 Life* life = static_cast<Life*>(instance->pdata);
382 return life;
383 }
384
385 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
386 if (NPPVpluginScriptableNPObject == variable) {
387 NPObject* scriptable_object = NPP_GetScriptableInstance(instance);
388 if (scriptable_object == NULL)
389 return NPERR_INVALID_INSTANCE_ERROR;
390 *reinterpret_cast<NPObject**>(value) = scriptable_object;
391 return NPERR_NO_ERROR;
392 }
393 return NPERR_INVALID_PARAM;
394 }
395
396 int16_t NPP_HandleEvent(NPP instance, void* event) {
397 Life* life = static_cast<Life*>(instance->pdata);
398 if (NULL != life) {
399 NPPepperEvent* npevent = static_cast<NPPepperEvent*>(event);
400 life->HandleEvent(npevent);
401 }
402 return 0;
403 }
404
405 NPError NPP_New(NPMIMEType mime_type,
406 NPP instance,
407 uint16_t mode,
408 int16_t argc,
409 char* argn[],
410 char* argv[],
411 NPSavedData* saved) {
412 if (instance == NULL) {
413 return NPERR_INVALID_INSTANCE_ERROR;
414 }
415
416 Life* const life = static_cast<Life*>(NPN_CreateObject(instance, &np_class));
417 instance->pdata = life;
418 return NPERR_NO_ERROR;
419 }
420
421 NPError NPP_SetWindow(NPP instance, NPWindow* window) {
422 if (instance == NULL) {
423 return NPERR_INVALID_INSTANCE_ERROR;
424 }
425 if (window == NULL) {
426 return NPERR_GENERIC_ERROR;
427 }
428 Life* life = static_cast<Life*>(instance->pdata);
429 if (life != NULL) {
430 return life->SetWindow(window);
431 }
432 return NPERR_NO_ERROR;
433 }
434
435 NPError NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) {
436 extern NPError InitializePluginFunctions(NPPluginFuncs* plugin_funcs);
437 return InitializePluginFunctions(plugin_funcs);
438 }
439
440 NPError InitializePluginFunctions(NPPluginFuncs* plugin_funcs) {
441 memset(plugin_funcs, 0, sizeof(*plugin_funcs));
442 plugin_funcs->version = NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL;
443 plugin_funcs->size = sizeof(*plugin_funcs);
444 plugin_funcs->newp = NPP_New;
445 plugin_funcs->destroy = NPP_Destroy;
446 plugin_funcs->setwindow = NPP_SetWindow;
447 plugin_funcs->event = NPP_HandleEvent;
448 plugin_funcs->getvalue = NPP_GetValue;
449 return NPERR_NO_ERROR;
450 }
451
452 NPError NP_Initialize(NPNetscapeFuncs* browser_functions,
453 NPPluginFuncs* plugin_functions) {
454 return NP_GetEntryPoints(plugin_functions);
455 }
456
457 NPError NP_Shutdown() {
458 return NPERR_NO_ERROR;
459 }
460
461 } // extern "C"
462 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698