Chromium Code Reviews| Index: examples/graphics/life/life.cc |
| =================================================================== |
| --- examples/graphics/life/life.cc (revision 158) |
| +++ examples/graphics/life/life.cc (working copy) |
| @@ -1,178 +1,91 @@ |
| -// Copyright 2010 The Native Client SDK Authors. All rights reserved. |
| +// Copyright 2011 The Native Client SDK Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can |
| // be found in the LICENSE file. |
| -#include <assert.h> |
| -#include <math.h> |
| -#include <stdlib.h> |
| -#include <string.h> |
| +#include "examples/graphics/life/life.h" |
| +#include <ppapi/cpp/completion_callback.h> |
| +#include <ppapi/cpp/var.h> |
| + |
| #include <algorithm> |
| +#include <cassert> |
| +#include <cmath> |
| +#include <cstdio> |
| +#include <cstring> |
| #include <string> |
| -#include <nacl/nacl_npapi.h> |
| -#include <nacl/npapi_extensions.h> |
| -#include <nacl/npupp.h> |
| - |
| -#define JS_LOG(msg) \ |
| - const size_t line_number = __LINE__; \ |
| - size_t len = floor(line_number) + 1; \ |
| - len = std::string(msg).size() + strlen(__FILE__) + len + 5; \ |
| - char buffer[len]; \ |
| - memset(buffer, 0, len); \ |
| - snprintf(buffer, len, "%s:%i - ", __FILE__, line_number); \ |
| - strncat(buffer, std::string(msg).c_str(), len - strlen(buffer)); \ |
| - Log(npp_, buffer); |
| - |
| namespace { |
| -// Log given message to javascript console. |
| -bool Log(NPP npp, const char* msg, ...) { |
| - bool rv = false; |
| - NPObject* window = NULL; |
| - if (NPERR_NO_ERROR == NPN_GetValue(npp, NPNVWindowNPObject, &window)) { |
| - const char buffer[] = "top.console"; |
| - NPString console_stript = { 0 }; |
| - console_stript.UTF8Length = strlen(buffer); |
| - console_stript.UTF8Characters = buffer; |
| - NPVariant console; |
| - if (NPN_Evaluate(npp, window, &console_stript, &console)) { |
| - if (NPVARIANT_IS_OBJECT(console)) { |
| - // Convert the message to NPString; |
| - NPVariant text; |
| - STRINGN_TO_NPVARIANT(msg, static_cast<uint32_t>(strlen(msg)), |
| - text); |
| - NPVariant result; |
| - if (NPN_Invoke(npp, NPVARIANT_TO_OBJECT(console), |
| - NPN_GetStringIdentifier("log"), &text, 1, &result)) { |
| - NPN_ReleaseVariantValue(&result); |
| - rv = true; |
| - } |
| - } |
| - NPN_ReleaseVariantValue(&console); |
| - } |
| - } |
| - return rv; |
| -} |
| +const char* const kUpdateMethodId = "update"; |
| +const char* const kAddCellAtPointMethodId = "addCellAtPoint"; |
| +const unsigned int kInitialRandSeed = 0xC0DE533D; |
| -// seed for rand_r() - we only call rand_r from main thread. |
| -static unsigned int gSeed = 0xC0DE533D; |
| - |
| -// random number helper |
| -// binary rand() returns 0 or 1 |
| -inline unsigned char brand() { |
| - return static_cast<unsigned char>(rand_r(&gSeed) & 1); |
| -} |
| - |
| inline uint32_t MakeRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { |
| return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); |
| } |
| -void FlushCallback(NPP instance, NPDeviceContext* context, |
| - NPError err, void* user_data) { |
| -} |
| +// Map of neighboring colors. |
| +const uint32_t kNeighborColors[] = { |
| + MakeRGBA(0x00, 0x00, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x40, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x60, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x80, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xA0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xC0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xE0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x00, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x40, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x60, 0x00, 0xff), |
| + MakeRGBA(0x00, 0x80, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xA0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xC0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xE0, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| + MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| +}; |
| -void* life(void* data); |
| +// These represent the new health value of a cell based on its neighboring |
| +// values. The health is binary: either alive or dead. |
| +const uint8_t kIsAlive[] = { |
| + 0, 0, 0, 1, 0, 0, 0, 0, 0, // Values if the center cell is dead. |
|
dmichael(do not use this one)
2011/02/03 21:22:59
Lint is complaining that you should have >=2 space
David Springer
2011/02/03 22:04:55
Done.
|
| + 0, 0, 1, 1, 0, 0, 0, 0, 0 // Values if the center cell is alive. |
| + }; |
| -// Life class holds information and functionality needed to render |
| -// life into an Pepper 2D surface. |
| -class Life : public NPObject { |
| - public: |
| - Life(NPP npp); |
| - ~Life(); |
| - NPError SetWindow(NPWindow* window); |
| - void Update(); |
| - void Plot(int x, int y); |
| - void Stir(); |
| - void Draw(); |
| - void UpdateCells(); |
| - void Swap(); |
| - void HandleEvent(NPPepperEvent* event); |
| +void FlushCallback(void* data, int32_t result) { |
| + static_cast<life::Life*>(data)->set_flush_pending(false); |
| +} |
| +} // namespace |
| - private: |
| - void CreateContext(); |
| - void DestroyContext(); |
| - bool IsContextValid() { |
| - return context2d_.region != NULL; |
| - } |
| - int width() const { |
| - return width_; |
| - } |
| - int height() const { |
| - return height_; |
| - } |
| - void* pixels() { |
| - return context2d_.region; |
| - } |
| - |
| - NPP npp_; |
| - NPExtensions* extensions_; |
| - int width_, height_; |
| - NPDevice* device2d_; // The PINPAPI 2D device. |
| - NPDeviceContext2D context2d_; // The PINPAPI 2D drawing context. |
| - bool scribble_; |
| - bool quit_; |
| - char *cell_in_; |
| - char *cell_out_; |
| -}; |
| - |
| -Life::Life(NPP npp) : npp_(npp), extensions_(NULL), width_(0), height_(0), |
| - device2d_(NULL), cell_in_(NULL), cell_out_(NULL) { |
| - memset(&context2d_, 0, sizeof(context2d_)); |
| - NPN_GetValue(npp_, NPNVPepperExtensions, &extensions_); |
| - device2d_ = extensions_->acquireDevice(npp_, NPPepper2DDevice); |
| - assert(extensions_); |
| +namespace life { |
| +Life::Life(PP_Instance instance) : pp::Instance(instance), |
| + graphics_2d_context_(NULL), |
| + pixel_buffer_(NULL), |
| + random_bits_(kInitialRandSeed), |
| + flush_pending_(false), |
| + cell_in_(NULL), |
| + cell_out_(NULL) { |
| } |
| Life::~Life() { |
| delete[] cell_in_; |
| delete[] cell_out_; |
| DestroyContext(); |
| + delete pixel_buffer_; |
| } |
| -void Life::CreateContext() { |
| - if (IsContextValid()) |
| - return; |
| - device2d_ = extensions_->acquireDevice(npp_, NPPepper2DDevice); |
| - assert(device2d_); |
| - NPDeviceContext2DConfig config; |
| - NPError init_err = device2d_->initializeContext(npp_, &config, &context2d_); |
| - assert(NPERR_NO_ERROR == init_err); |
| +pp::Var Life::GetInstanceObject() { |
| + LifeScriptObject* script_object = new LifeScriptObject(this); |
| + return pp::Var(this, script_object); |
| } |
| -void Life::HandleEvent(NPPepperEvent* event) { |
| - bool plot = false; |
| - if (event->type == NPEventType_MouseDown) { |
| - scribble_ = true; |
| - plot = true; |
| - } |
| - if (event->type == NPEventType_MouseUp) { |
| - JS_LOG("MouseUp event"); |
| - scribble_ = false; |
| - } |
| - if (event->type == NPEventType_MouseMove) { |
| - plot = scribble_; |
| - } |
| - if (plot) { |
| - // place a blob of life |
| - Plot(event->u.mouse.x - 1, event->u.mouse.y - 1); |
| - Plot(event->u.mouse.x + 0, event->u.mouse.y - 1); |
| - Plot(event->u.mouse.x + 1, event->u.mouse.y - 1); |
| - Plot(event->u.mouse.x - 1, event->u.mouse.y + 0); |
| - Plot(event->u.mouse.x + 0, event->u.mouse.y + 0); |
| - Plot(event->u.mouse.x + 1, event->u.mouse.y + 0); |
| - Plot(event->u.mouse.x - 1, event->u.mouse.y + 1); |
| - Plot(event->u.mouse.x + 0, event->u.mouse.y + 1); |
| - Plot(event->u.mouse.x + 1, event->u.mouse.y + 1); |
| - } |
| +bool Life::Init(uint32_t argc, const char* argn[], const char* argv[]) { |
| + return true; |
| } |
| -void Life::DestroyContext() { |
| - if (!IsContextValid()) |
| - return; |
| - device2d_->destroyContext(npp_, &context2d_); |
| -} |
| - |
| void Life::Plot(int x, int y) { |
| + if (cell_in_ == NULL) |
| + return; |
| if (x < 0) return; |
| if (x >= width()) return; |
| if (y < 0) return; |
| @@ -180,283 +93,168 @@ |
| *(cell_in_ + x + y * width()) = 1; |
| } |
| -NPError Life::SetWindow(NPWindow* window) { |
| - if (!window) |
| - return NPERR_NO_ERROR; |
| - width_ = window->width; |
| - height_ = window->height; |
| - if (!IsContextValid()) |
| - CreateContext(); |
| +void Life::DidChangeView(const pp::Rect& position, const pp::Rect& clip) { |
| + if (position.size().width() == width() && |
| + position.size().height() == height()) |
| + return; // Size didn't change, no need to update anything. |
| - const size_t size = width() * height(); |
| + // Create a new device context with the new size. |
| + DestroyContext(); |
| + CreateContext(position.size()); |
| + // Delete the old pixel buffer and create a new one. |
| + delete pixel_buffer_; |
| delete[] cell_in_; |
| delete[] cell_out_; |
| - cell_in_ = new char[size]; |
| - cell_out_ = new char[size]; |
| - std::fill(cell_in_, cell_in_ + size, 0); |
| - std::fill(cell_out_, cell_out_ + size, 0); |
| - |
| - NPDeviceFlushContextCallbackPtr callback = |
| - reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); |
| - device2d_->flushContext(npp_, &context2d_, callback, NULL); |
| - return NPERR_NO_ERROR; |
| + pixel_buffer_ = NULL; |
| + cell_in_ = cell_out_ = NULL; |
| + if (graphics_2d_context_ != NULL) { |
| + pixel_buffer_ = new pp::ImageData(this, |
| + PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
| + graphics_2d_context_->size(), |
| + false); |
| + const size_t size = width() * height(); |
| + cell_in_ = new uint8_t[size]; |
| + cell_out_ = new uint8_t[size]; |
| + std::fill(cell_in_, cell_in_ + size, 0); |
| + std::fill(cell_out_, cell_out_ + size, 0); |
| + } |
| } |
| void Life::Update() { |
| Stir(); |
| UpdateCells(); |
| Swap(); |
| - NPDeviceFlushContextCallbackPtr callback = |
| - reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); |
| - device2d_->flushContext(npp_, &context2d_, callback, NULL); |
| + FlushPixelBuffer(); |
| } |
| +void Life::AddCellAtPoint(const pp::Var& var_x, const pp::Var& var_y) { |
| + if (!var_x.is_number() || !var_y.is_number()) |
| + return; |
| + int32_t x, y; |
| + x = var_x.is_int() ? var_x.AsInt() : static_cast<int32_t>(var_x.AsDouble()); |
| + y = var_y.is_int() ? var_y.AsInt() : static_cast<int32_t>(var_y.AsDouble()); |
| + Plot(x - 1, y - 1); |
| + Plot(x + 0, y - 1); |
| + Plot(x + 1, y - 1); |
| + Plot(x - 1, y + 0); |
| + Plot(x + 0, y + 0); |
| + Plot(x + 1, y + 0); |
| + Plot(x - 1, y + 1); |
| + Plot(x + 0, y + 1); |
| + Plot(x + 1, y + 1); |
| +} |
| + |
| void Life::Stir() { |
| + if (cell_in_ == NULL || cell_out_ == NULL) |
| + return; |
| const int height = this->height(); |
| const int width = this->width(); |
| for (int i = 0; i < width; ++i) { |
| - cell_in_[i] = brand(); |
| - cell_in_[i + (height - 1) * width] = brand(); |
| + cell_in_[i] = random_bits_.value(); |
| + cell_in_[i + (height - 1) * width] = random_bits_.value(); |
| } |
| for (int i = 0; i < height; ++i) { |
| - cell_in_[i * width] = brand(); |
| - cell_in_[i * width + (width - 2)] = brand(); |
| + cell_in_[i * width] = random_bits_.value(); |
| + cell_in_[i * width + (width - 2)] = random_bits_.value(); |
|
dmichael(do not use this one)
2011/02/03 21:22:59
Still a little baffled by this, but let's stick wi
David Springer
2011/02/03 22:04:55
Done.
|
| } |
| } |
| void Life::UpdateCells() { |
| - // map neighbor count to color |
| - static unsigned int colors[18] = { |
| - MakeRGBA(0x00, 0x00, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x40, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x60, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x80, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xA0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xC0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xE0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x00, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x40, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x60, 0x00, 0xff), |
| - MakeRGBA(0x00, 0x80, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xA0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xC0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xE0, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| - MakeRGBA(0x00, 0xFF, 0x00, 0xff), |
| - }; |
| - // map neighbor count to alive/dead |
| - static char replace[18] = { |
| - 0, 0, 0, 1, 0, 0, 0, 0, // row for center cell dead |
| - 0, 0, 1, 1, 0, 0, 0, 0, // row for center cell alive |
| - }; |
| + if (cell_in_ == NULL || cell_out_ == NULL || pixels() == NULL) |
| + return; |
| const int height = this->height(); |
| const int width = this->width(); |
| - // do neighbor sumation; apply rules, output pixel color |
| + // Do neighbor sumation; apply rules, output pixel color. |
| for (int y = 1; y < (height - 1); ++y) { |
| - char *src0 = cell_in_ + (y - 1) * width; |
| - char *src1 = cell_in_ + (y) * width; |
| - char *src2 = cell_in_ + (y + 1) * width; |
| + uint8_t *src0 = cell_in_ + (y - 1) * width; |
| + uint8_t *src1 = cell_in_ + (y) * width; |
| + uint8_t *src2 = cell_in_ + (y + 1) * width; |
| int count; |
| - unsigned int color; |
| - char *dst = cell_out_ + (y) * width; |
| - uint32_t *pixels = static_cast<uint32_t*>(this->pixels()) + y * width; |
| + uint32_t color; |
| + uint8_t *dst = cell_out_ + (y) * width; |
| + uint32_t *pixel_buffer = pixels() + y * width; |
| for (int x = 1; x < (width - 1); ++x) { |
| - // build sum, weight center by 8x |
| + // Build sum, weight center by 9x. Note that an alive center with all |
| + // dead neighbors produces the same result as a dead center with all |
| + // alive neighbors. |
|
dmichael(do not use this one)
2011/02/03 21:22:59
the 'Note that' part is no longer true with this l
David Springer
2011/02/03 22:04:55
Done.
|
| count = src0[-1] + src0[0] + src0[1] + |
| - src1[-1] + src1[0] * 8 + src1[1] + |
| + src1[-1] + src1[0] * 9 + src1[1] + |
| src2[-1] + src2[0] + src2[1]; |
| - color = colors[count]; |
| - *pixels++ = color; |
| - *dst++ = replace[count]; |
| + color = kNeighborColors[count]; |
| + *pixel_buffer++ = color; |
| + *dst++ = kIsAlive[count]; |
| ++src0, ++src1, ++src2; |
| } |
| } |
| } |
| void Life::Swap() { |
| - char* tmp = cell_in_; |
| + uint8_t* tmp = cell_in_; |
| cell_in_ = cell_out_; |
| cell_out_ = tmp; |
| } |
| -extern "C" { |
| - |
| -// The following functions implement functions to be used with npruntime. |
| -static NPObject* AllocateLife(NPP npp, NPClass* npclass) { |
| - Life* rv = new Life(npp); |
| - return rv; |
| -} |
| - |
| -static void Deallocate(NPObject* obj) { |
| - Life* const life = static_cast<Life*>(obj); |
| - delete life; |
| -} |
| - |
| -// These are for npruntime. |
| -static void Invalidate(NPObject*) { |
| -} |
| - |
| -static bool HasMethod(NPObject*, NPIdentifier name) { |
| - bool rv = false; |
| - NPUTF8* method_name = NPN_UTF8FromIdentifier(name); |
| - if (0 == memcmp(method_name, "update", sizeof("update"))) { |
| - rv = true; |
| +void Life::CreateContext(const pp::Size& size) { |
| + if (IsContextValid()) |
| + return; |
| + graphics_2d_context_ = new pp::Graphics2D(this, size, false); |
| + if (!BindGraphics(*graphics_2d_context_)) { |
| + printf("Couldn't bind the device context\n"); |
| } |
| - NPN_MemFree(method_name); |
| - return rv; |
| } |
| -static bool Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, |
| - uint32_t argc, NPVariant *result) { |
| - bool rv = false; |
| - NPUTF8* method_name = NPN_UTF8FromIdentifier(name); |
| - if (0 == memcmp(method_name, "update", sizeof("update"))) { |
| - rv = true; |
| - Life* const life = static_cast<Life*>(obj); |
| - life->Update(); |
| - } |
| - NPN_MemFree(method_name); |
| - return rv; |
| +void Life::DestroyContext() { |
| + if (!IsContextValid()) |
| + return; |
| + delete graphics_2d_context_; |
| + graphics_2d_context_ = NULL; |
| } |
| -static bool InvokeDefault(NPObject *npobj, const NPVariant *args, |
| - uint32_t argCount, NPVariant *result) { |
| - return false; |
| +void Life::FlushPixelBuffer() { |
| + if (!IsContextValid()) |
| + return; |
| + graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point()); |
| + if (flush_pending()) |
| + return; |
| + set_flush_pending(true); |
| + graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this)); |
| } |
| -static bool HasProperty(NPObject *npobj, NPIdentifier name) { |
| - return false; |
| -} |
| - |
| -static bool GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) { |
| - return false; |
| -} |
| - |
| -static bool SetProperty(NPObject *npobj, NPIdentifier name, |
| - const NPVariant *value) { |
| - return false; |
| -} |
| - |
| -static bool RemoveProperty(NPObject *npobj, NPIdentifier name) { |
| - return false; |
| -} |
| - |
| -NPClass np_class = { |
| - NP_CLASS_STRUCT_VERSION, |
| - AllocateLife, |
| - Deallocate, |
| - Invalidate, |
| - HasMethod, |
| - Invoke, |
| - InvokeDefault, |
| - HasProperty, |
| - GetProperty, |
| - SetProperty, |
| - RemoveProperty |
| -}; |
| - |
| -// These functions are required by both the develop and publish versions, |
| -// they are called when a module instance is first loaded, and when the module |
| -// instance is finally deleted. They must use C-style linkage. |
| -NPError NPP_Destroy(NPP instance, NPSavedData** save) { |
| - if (instance == NULL) { |
| - return NPERR_INVALID_INSTANCE_ERROR; |
| +bool Life::LifeScriptObject::HasMethod( |
| + const pp::Var& method, |
| + pp::Var* exception) { |
| + if (!method.is_string()) { |
| + return false; |
| } |
| - |
| - Life* life = static_cast<Life*>(instance->pdata); |
| - if (life != NULL) { |
| - NPN_ReleaseObject(life); |
| - } |
| - return NPERR_NO_ERROR; |
| + std::string method_name = method.AsString(); |
| + return method_name == kUpdateMethodId || |
| + method_name == kAddCellAtPointMethodId; |
| } |
| -// NPP_GetScriptableInstance retruns the NPObject pointer that corresponds to |
| -// NPPVpluginScriptableNPObject queried by NPP_GetValue() from the browser. |
| -NPObject* NPP_GetScriptableInstance(NPP instance) { |
| - if (instance == NULL) { |
| - return NULL; |
| +pp::Var Life::LifeScriptObject::Call( |
| + const pp::Var& method, |
| + const std::vector<pp::Var>& args, |
| + pp::Var* exception) { |
| + if (!method.is_string()) { |
| + return pp::Var(false); |
| } |
| - Life* life = static_cast<Life*>(instance->pdata); |
| - return life; |
| -} |
| - |
| -NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { |
| - if (NPPVpluginScriptableNPObject == variable) { |
| - NPObject* scriptable_object = NPP_GetScriptableInstance(instance); |
| - if (scriptable_object == NULL) |
| - return NPERR_INVALID_INSTANCE_ERROR; |
| - *reinterpret_cast<NPObject**>(value) = scriptable_object; |
| - return NPERR_NO_ERROR; |
| + std::string method_name = method.AsString(); |
| + if (app_instance_ != NULL) { |
| + if (method_name == kUpdateMethodId) { |
| + app_instance_->Update(); |
| + } else if (method_name == kAddCellAtPointMethodId) { |
| + // Pull off the first two params. |
| + if (args.size() < 2) |
| + return pp::Var(false); |
| + app_instance_->AddCellAtPoint(args[0], args[1]); |
| + } |
| } |
| - return NPERR_INVALID_PARAM; |
| + return pp::Var(); |
| } |
| -int16_t NPP_HandleEvent(NPP instance, void* event) { |
| - Life* life = static_cast<Life*>(instance->pdata); |
| - if (NULL != life) { |
| - NPPepperEvent* npevent = static_cast<NPPepperEvent*>(event); |
| - life->HandleEvent(npevent); |
| - } |
| - return 0; |
| +uint8_t Life::RandomBitGenerator::value() { |
| + return static_cast<uint8_t>(rand_r(&random_bit_seed_) & 1); |
| } |
| -NPError NPP_New(NPMIMEType mime_type, |
| - NPP instance, |
| - uint16_t mode, |
| - int16_t argc, |
| - char* argn[], |
| - char* argv[], |
| - NPSavedData* saved) { |
| - if (instance == NULL) { |
| - return NPERR_INVALID_INSTANCE_ERROR; |
| - } |
| +} // namespace life |
| - Life* const life = static_cast<Life*>(NPN_CreateObject(instance, &np_class)); |
| - instance->pdata = life; |
| - return NPERR_NO_ERROR; |
| -} |
| - |
| -NPError NPP_SetWindow(NPP instance, NPWindow* window) { |
| - if (instance == NULL) { |
| - return NPERR_INVALID_INSTANCE_ERROR; |
| - } |
| - if (window == NULL) { |
| - return NPERR_GENERIC_ERROR; |
| - } |
| - Life* life = static_cast<Life*>(instance->pdata); |
| - if (life != NULL) { |
| - return life->SetWindow(window); |
| - } |
| - return NPERR_NO_ERROR; |
| -} |
| - |
| -NPError NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) { |
| - extern NPError InitializePluginFunctions(NPPluginFuncs* plugin_funcs); |
| - return InitializePluginFunctions(plugin_funcs); |
| -} |
| - |
| -NPError InitializePluginFunctions(NPPluginFuncs* plugin_funcs) { |
| - memset(plugin_funcs, 0, sizeof(*plugin_funcs)); |
| - plugin_funcs->version = NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; |
| - plugin_funcs->size = sizeof(*plugin_funcs); |
| - plugin_funcs->newp = NPP_New; |
| - plugin_funcs->destroy = NPP_Destroy; |
| - plugin_funcs->setwindow = NPP_SetWindow; |
| - plugin_funcs->event = NPP_HandleEvent; |
| - plugin_funcs->getvalue = NPP_GetValue; |
| - return NPERR_NO_ERROR; |
| -} |
| - |
| -NPError NP_Initialize(NPNetscapeFuncs* browser_functions, |
| - NPPluginFuncs* plugin_functions) { |
| - return NP_GetEntryPoints(plugin_functions); |
| -} |
| - |
| -NPError NP_Shutdown() { |
| - return NPERR_NO_ERROR; |
| -} |
| - |
| -} // extern "C" |
| -} |
| Property changes on: examples/graphics/life/life.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |