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

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
« no previous file with comments | « examples/graphics/life/life.h ('k') | examples/graphics/life/life.css » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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; 20 const unsigned int kInitialRandSeed = 0xC0DE533D;
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 21
66 inline uint32_t MakeRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { 22 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)); 23 return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
68 } 24 }
69 25
70 void FlushCallback(NPP instance, NPDeviceContext* context, 26 // Map of neighboring colors.
71 NPError err, void* user_data) { 27 const uint32_t kNeighborColors[] = {
72 } 28 MakeRGBA(0x00, 0x00, 0x00, 0xff),
73 29 MakeRGBA(0x00, 0x40, 0x00, 0xff),
74 void* life(void* data); 30 MakeRGBA(0x00, 0x60, 0x00, 0xff),
75 31 MakeRGBA(0x00, 0x80, 0x00, 0xff),
76 // Life class holds information and functionality needed to render 32 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
77 // life into an Pepper 2D surface. 33 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
78 class Life : public NPObject { 34 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
79 public: 35 MakeRGBA(0x00, 0x00, 0x00, 0xff),
80 Life(NPP npp); 36 MakeRGBA(0x00, 0x40, 0x00, 0xff),
81 ~Life(); 37 MakeRGBA(0x00, 0x60, 0x00, 0xff),
82 NPError SetWindow(NPWindow* window); 38 MakeRGBA(0x00, 0x80, 0x00, 0xff),
83 void Update(); 39 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
84 void Plot(int x, int y); 40 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
85 void Stir(); 41 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
86 void Draw(); 42 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
87 void UpdateCells(); 43 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
88 void Swap(); 44 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
89 void HandleEvent(NPPepperEvent* event); 45 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 }; 46 };
117 47
118 Life::Life(NPP npp) : npp_(npp), extensions_(NULL), width_(0), height_(0), 48 // These represent the new health value of a cell based on its neighboring
119 device2d_(NULL), cell_in_(NULL), cell_out_(NULL) { 49 // values. The health is binary: either alive or dead.
120 memset(&context2d_, 0, sizeof(context2d_)); 50 const uint8_t kIsAlive[] = {
121 NPN_GetValue(npp_, NPNVPepperExtensions, &extensions_); 51 0, 0, 0, 1, 0, 0, 0, 0, 0, // Values if the center cell is dead.
122 device2d_ = extensions_->acquireDevice(npp_, NPPepper2DDevice); 52 0, 0, 1, 1, 0, 0, 0, 0, 0 // Values if the center cell is alive.
123 assert(extensions_); 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 random_bits_(kInitialRandSeed),
65 flush_pending_(false),
66 cell_in_(NULL),
67 cell_out_(NULL) {
124 } 68 }
125 69
126 Life::~Life() { 70 Life::~Life() {
127 delete[] cell_in_; 71 delete[] cell_in_;
128 delete[] cell_out_; 72 delete[] cell_out_;
129 DestroyContext(); 73 DestroyContext();
74 delete pixel_buffer_;
130 } 75 }
131 76
132 void Life::CreateContext() { 77 pp::Var Life::GetInstanceObject() {
133 if (IsContextValid()) 78 LifeScriptObject* script_object = new LifeScriptObject(this);
134 return; 79 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 } 80 }
141 81
142 void Life::HandleEvent(NPPepperEvent* event) { 82 bool Life::Init(uint32_t argc, const char* argn[], const char* argv[]) {
143 bool plot = false; 83 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 } 84 }
174 85
175 void Life::Plot(int x, int y) { 86 void Life::Plot(int x, int y) {
87 if (cell_in_ == NULL)
88 return;
176 if (x < 0) return; 89 if (x < 0) return;
177 if (x >= width()) return; 90 if (x >= width()) return;
178 if (y < 0) return; 91 if (y < 0) return;
179 if (y >= height()) return; 92 if (y >= height()) return;
180 *(cell_in_ + x + y * width()) = 1; 93 *(cell_in_ + x + y * width()) = 1;
181 } 94 }
182 95
183 NPError Life::SetWindow(NPWindow* window) { 96 void Life::DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
184 if (!window) 97 if (position.size().width() == width() &&
185 return NPERR_NO_ERROR; 98 position.size().height() == height())
186 width_ = window->width; 99 return; // Size didn't change, no need to update anything.
187 height_ = window->height;
188 if (!IsContextValid())
189 CreateContext();
190 100
191 const size_t size = width() * height(); 101 // Create a new device context with the new size.
102 DestroyContext();
103 CreateContext(position.size());
104 // Delete the old pixel buffer and create a new one.
105 delete pixel_buffer_;
192 delete[] cell_in_; 106 delete[] cell_in_;
193 delete[] cell_out_; 107 delete[] cell_out_;
194 cell_in_ = new char[size]; 108 pixel_buffer_ = NULL;
195 cell_out_ = new char[size]; 109 cell_in_ = cell_out_ = NULL;
196 std::fill(cell_in_, cell_in_ + size, 0); 110 if (graphics_2d_context_ != NULL) {
197 std::fill(cell_out_, cell_out_ + size, 0); 111 pixel_buffer_ = new pp::ImageData(this,
198 112 PP_IMAGEDATAFORMAT_BGRA_PREMUL,
199 NPDeviceFlushContextCallbackPtr callback = 113 graphics_2d_context_->size(),
200 reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); 114 false);
201 device2d_->flushContext(npp_, &context2d_, callback, NULL); 115 const size_t size = width() * height();
202 return NPERR_NO_ERROR; 116 cell_in_ = new uint8_t[size];
117 cell_out_ = new uint8_t[size];
118 std::fill(cell_in_, cell_in_ + size, 0);
119 std::fill(cell_out_, cell_out_ + size, 0);
120 }
203 } 121 }
204 122
205 void Life::Update() { 123 void Life::Update() {
206 Stir(); 124 Stir();
207 UpdateCells(); 125 UpdateCells();
208 Swap(); 126 Swap();
209 NPDeviceFlushContextCallbackPtr callback = 127 FlushPixelBuffer();
210 reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); 128 }
211 device2d_->flushContext(npp_, &context2d_, callback, NULL); 129
130 void Life::AddCellAtPoint(const pp::Var& var_x, const pp::Var& var_y) {
131 if (!var_x.is_number() || !var_y.is_number())
132 return;
133 int32_t x, y;
134 x = var_x.is_int() ? var_x.AsInt() : static_cast<int32_t>(var_x.AsDouble());
135 y = var_y.is_int() ? var_y.AsInt() : static_cast<int32_t>(var_y.AsDouble());
136 Plot(x - 1, y - 1);
137 Plot(x + 0, y - 1);
138 Plot(x + 1, y - 1);
139 Plot(x - 1, y + 0);
140 Plot(x + 0, y + 0);
141 Plot(x + 1, y + 0);
142 Plot(x - 1, y + 1);
143 Plot(x + 0, y + 1);
144 Plot(x + 1, y + 1);
212 } 145 }
213 146
214 void Life::Stir() { 147 void Life::Stir() {
148 if (cell_in_ == NULL || cell_out_ == NULL)
149 return;
215 const int height = this->height(); 150 const int height = this->height();
216 const int width = this->width(); 151 const int width = this->width();
217 for (int i = 0; i < width; ++i) { 152 for (int i = 0; i < width; ++i) {
218 cell_in_[i] = brand(); 153 cell_in_[i] = random_bits_.value();
219 cell_in_[i + (height - 1) * width] = brand(); 154 cell_in_[i + (height - 1) * width] = random_bits_.value();
220 } 155 }
221 for (int i = 0; i < height; ++i) { 156 for (int i = 0; i < height; ++i) {
222 cell_in_[i * width] = brand(); 157 cell_in_[i * width] = random_bits_.value();
223 cell_in_[i * width + (width - 2)] = brand(); 158 cell_in_[i * width + (width - 1)] = random_bits_.value();
224 } 159 }
225 } 160 }
226 161
227 void Life::UpdateCells() { 162 void Life::UpdateCells() {
228 // map neighbor count to color 163 if (cell_in_ == NULL || cell_out_ == NULL || pixels() == NULL)
229 static unsigned int colors[18] = { 164 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(); 165 const int height = this->height();
255 const int width = this->width(); 166 const int width = this->width();
256 // do neighbor sumation; apply rules, output pixel color 167 // Do neighbor sumation; apply rules, output pixel color.
257 for (int y = 1; y < (height - 1); ++y) { 168 for (int y = 1; y < (height - 1); ++y) {
258 char *src0 = cell_in_ + (y - 1) * width; 169 uint8_t *src0 = (cell_in_ + (y - 1) * width) + 1;
259 char *src1 = cell_in_ + (y) * width; 170 uint8_t *src1 = src0 + width;
260 char *src2 = cell_in_ + (y + 1) * width; 171 uint8_t *src2 = src1 + width;
261 int count; 172 int count;
262 unsigned int color; 173 uint32_t color;
263 char *dst = cell_out_ + (y) * width; 174 uint8_t *dst = (cell_out_ + (y) * width) + 1;
264 uint32_t *pixels = static_cast<uint32_t*>(this->pixels()) + y * width; 175 uint32_t *pixel_buffer = pixels() + y * width;
265 for (int x = 1; x < (width - 1); ++x) { 176 for (int x = 1; x < (width - 1); ++x) {
266 // build sum, weight center by 8x 177 // Build sum, weight center by 9x.
267 count = src0[-1] + src0[0] + src0[1] + 178 count = src0[-1] + src0[0] + src0[1] +
268 src1[-1] + src1[0] * 8 + src1[1] + 179 src1[-1] + src1[0] * 9 + src1[1] +
269 src2[-1] + src2[0] + src2[1]; 180 src2[-1] + src2[0] + src2[1];
270 color = colors[count]; 181 color = kNeighborColors[count];
271 *pixels++ = color; 182 *pixel_buffer++ = color;
272 *dst++ = replace[count]; 183 *dst++ = kIsAlive[count];
273 ++src0, ++src1, ++src2; 184 ++src0;
185 ++src1;
186 ++src2;
274 } 187 }
275 } 188 }
276 } 189 }
277 190
278 void Life::Swap() { 191 void Life::Swap() {
279 char* tmp = cell_in_; 192 uint8_t* tmp = cell_in_;
280 cell_in_ = cell_out_; 193 cell_in_ = cell_out_;
281 cell_out_ = tmp; 194 cell_out_ = tmp;
282 } 195 }
283 196
284 extern "C" { 197 void Life::CreateContext(const pp::Size& size) {
285 198 if (IsContextValid())
286 // The following functions implement functions to be used with npruntime. 199 return;
287 static NPObject* AllocateLife(NPP npp, NPClass* npclass) { 200 graphics_2d_context_ = new pp::Graphics2D(this, size, false);
288 Life* rv = new Life(npp); 201 if (!BindGraphics(*graphics_2d_context_)) {
289 return rv; 202 printf("Couldn't bind the device context\n");
203 }
290 } 204 }
291 205
292 static void Deallocate(NPObject* obj) { 206 void Life::DestroyContext() {
293 Life* const life = static_cast<Life*>(obj); 207 if (!IsContextValid())
294 delete life; 208 return;
209 delete graphics_2d_context_;
210 graphics_2d_context_ = NULL;
295 } 211 }
296 212
297 // These are for npruntime. 213 void Life::FlushPixelBuffer() {
298 static void Invalidate(NPObject*) { 214 if (!IsContextValid())
215 return;
216 graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point());
217 if (flush_pending())
218 return;
219 set_flush_pending(true);
220 graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this));
299 } 221 }
300 222
301 static bool HasMethod(NPObject*, NPIdentifier name) { 223 bool Life::LifeScriptObject::HasMethod(
302 bool rv = false; 224 const pp::Var& method,
303 NPUTF8* method_name = NPN_UTF8FromIdentifier(name); 225 pp::Var* exception) {
304 if (0 == memcmp(method_name, "update", sizeof("update"))) { 226 if (!method.is_string()) {
305 rv = true; 227 return false;
306 } 228 }
307 NPN_MemFree(method_name); 229 std::string method_name = method.AsString();
308 return rv; 230 return method_name == kUpdateMethodId ||
231 method_name == kAddCellAtPointMethodId;
309 } 232 }
310 233
311 static bool Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, 234 pp::Var Life::LifeScriptObject::Call(
312 uint32_t argc, NPVariant *result) { 235 const pp::Var& method,
313 bool rv = false; 236 const std::vector<pp::Var>& args,
314 NPUTF8* method_name = NPN_UTF8FromIdentifier(name); 237 pp::Var* exception) {
315 if (0 == memcmp(method_name, "update", sizeof("update"))) { 238 if (!method.is_string()) {
316 rv = true; 239 return pp::Var(false);
317 Life* const life = static_cast<Life*>(obj);
318 life->Update();
319 } 240 }
320 NPN_MemFree(method_name); 241 std::string method_name = method.AsString();
321 return rv; 242 if (app_instance_ != NULL) {
243 if (method_name == kUpdateMethodId) {
244 app_instance_->Update();
245 } else if (method_name == kAddCellAtPointMethodId) {
246 // Pull off the first two params.
247 if (args.size() < 2)
248 return pp::Var(false);
249 app_instance_->AddCellAtPoint(args[0], args[1]);
250 }
251 }
252 return pp::Var();
322 } 253 }
323 254
324 static bool InvokeDefault(NPObject *npobj, const NPVariant *args, 255 uint8_t Life::RandomBitGenerator::value() {
325 uint32_t argCount, NPVariant *result) { 256 return static_cast<uint8_t>(rand_r(&random_bit_seed_) & 1);
326 return false;
327 } 257 }
328 258
329 static bool HasProperty(NPObject *npobj, NPIdentifier name) { 259 } // namespace life
330 return false;
331 }
332 260
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
« no previous file with comments | « examples/graphics/life/life.h ('k') | examples/graphics/life/life.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698