Restructuring the sample plugin and adding more tests.

This commit is contained in:
Derek Sollenberger
2009-06-18 11:19:41 -04:00
parent 246ad9119a
commit d7ebf27ff4
16 changed files with 595 additions and 253 deletions

View File

@@ -30,10 +30,13 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
main.cpp \ main.cpp \
PluginObject.cpp \ PluginObject.cpp \
pluginGraphics.cpp animation/AnimationPlugin.cpp \
background/BackgroundPlugin.cpp
LOCAL_C_INCLUDES += \ LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \ $(LOCAL_PATH) \
$(LOCAL_PATH)/animation \
$(LOCAL_PATH)/background \
external/webkit/WebCore/bridge \ external/webkit/WebCore/bridge \
external/webkit/WebCore/plugins \ external/webkit/WebCore/plugins \
external/webkit/WebCore/platform/android/JavaVM \ external/webkit/WebCore/platform/android/JavaVM \

View File

@@ -175,4 +175,3 @@ static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *cou
{ {
return false; return false;
} }

View File

@@ -34,16 +34,18 @@
#ifndef PluginObject__DEFINED #ifndef PluginObject__DEFINED
#define PluginObject__DEFINED #define PluginObject__DEFINED
#include "npapi.h" #include "main.h"
struct ANPEvent;
struct ANPCanvas; struct ANPCanvas;
struct ANPAudioTrack; struct ANPAudioTrack;
class Animation { class SubPlugin {
public: public:
Animation(NPP inst) : m_inst(inst) {} SubPlugin(NPP inst) : m_inst(inst) {}
virtual ~Animation() {} virtual ~SubPlugin() {}
virtual void draw(ANPCanvas*) = 0; virtual void draw(ANPCanvas*) = 0;
virtual int16 handleEvent(const ANPEvent* evt) = 0;
NPP inst() const { return m_inst; } NPP inst() const { return m_inst; }
@@ -51,18 +53,24 @@ private:
NPP m_inst; NPP m_inst;
}; };
enum PluginTypes {
kBackground_PluginType = 1,
kAnimation_PluginType = 2,
kAudio_PluginType = 3,
kText_PluginType = 4,
kPaint_PluginType = 5
};
typedef uint32_t PluginType;
typedef struct PluginObject { typedef struct PluginObject {
NPObject header; NPObject header;
NPP npp; NPP npp;
NPWindow* window; NPWindow* window;
Animation* anim;
ANPAudioTrack* track;
int32_t mUnichar;
bool mTestTimers; PluginType pluginType;
uint32_t mStartTime; SubPlugin* activePlugin;
uint32_t mPrevTime; ANPAudioTrack* track;
int mTimerCount;
} PluginObject; } PluginObject;
NPClass *getPluginClass(void); NPClass *getPluginClass(void);

View File

@@ -23,9 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "pluginGraphics.h" #include "AnimationPlugin.h"
#include "android_npapi.h"
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
@@ -63,6 +62,20 @@ static void inval(NPP instance, const ANPRectF& r, bool doAA) {
browser->invalidaterect(instance, &inval); browser->invalidaterect(instance, &inval);
} }
static void drawPlugin(SubPlugin* plugin, const ANPBitmap& bitmap, const ANPRectI& clip) {
ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
ANPRectF clipR;
clipR.left = clip.left;
clipR.top = clip.top;
clipR.right = clip.right;
clipR.bottom = clip.bottom;
gCanvasI.clipRect(canvas, &clipR);
plugin->draw(canvas);
gCanvasI.deleteCanvas(canvas);
}
uint32_t getMSecs() { uint32_t getMSecs() {
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
@@ -71,24 +84,7 @@ uint32_t getMSecs() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class BallAnimation : public Animation { BallAnimation::BallAnimation(NPP inst) : SubPlugin(inst) {
public:
BallAnimation(NPP inst);
virtual ~BallAnimation();
virtual void draw(ANPCanvas*);
private:
float m_x;
float m_y;
float m_dx;
float m_dy;
ANPRectF m_oval;
ANPPaint* m_paint;
static const float SCALE = 0.1;
};
BallAnimation::BallAnimation(NPP inst) : Animation(inst) {
m_x = m_y = 0; m_x = m_y = 0;
m_dx = 7 * SCALE; m_dx = 7 * SCALE;
m_dy = 5 * SCALE; m_dy = 5 * SCALE;
@@ -103,6 +99,13 @@ BallAnimation::BallAnimation(NPP inst) : Animation(inst) {
ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle); ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
gPaintI.setTypeface(m_paint, tf); gPaintI.setTypeface(m_paint, tf);
gTypefaceI.unref(tf); gTypefaceI.unref(tf);
//register for key and touch events
ANPEventFlags flags = kKey_ANPEventFlag | kTouch_ANPEventFlag;
NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
if (err != NPERR_NO_ERROR) {
gLogI.log(inst, kError_ANPLogType, "Error selecting input events.");
}
} }
BallAnimation::~BallAnimation() { BallAnimation::~BallAnimation() {
@@ -173,38 +176,39 @@ void BallAnimation::draw(ANPCanvas* canvas) {
bounce(&m_x, &m_dx, obj->window->width - OW); bounce(&m_x, &m_dx, obj->window->width - OW);
bounce(&m_y, &m_dy, obj->window->height - OH); bounce(&m_y, &m_dy, obj->window->height - OH);
if (obj->mUnichar) { if (mUnichar) {
ANPFontMetrics fm; ANPFontMetrics fm;
gPaintI.getFontMetrics(m_paint, &fm); gPaintI.getFontMetrics(m_paint, &fm);
gPaintI.setColor(m_paint, 0xFF0000FF); gPaintI.setColor(m_paint, 0xFF0000FF);
char c = static_cast<char>(obj->mUnichar); char c = static_cast<char>(mUnichar);
gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint); gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint);
} }
} }
/////////////////////////////////////////////////////////////////////////////// int16 BallAnimation::handleEvent(const ANPEvent* evt) {
NPP instance = this->inst();
void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip) { switch (evt->eventType) {
ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap); case kDraw_ANPEventType:
switch (evt->data.draw.model) {
ANPRectF clipR; case kBitmap_ANPDrawingModel:
clipR.left = clip.left; drawPlugin(this, evt->data.draw.data.bitmap, evt->data.draw.clip);
clipR.top = clip.top; return 1;
clipR.right = clip.right; default:
clipR.bottom = clip.bottom; break; // unknown drawing model
gCanvasI.clipRect(canvas, &clipR);
drawPlugin(instance, canvas);
gCanvasI.deleteCanvas(canvas);
} }
void drawPlugin(NPP instance, ANPCanvas* canvas) { case kKey_ANPEventType:
PluginObject *obj = (PluginObject*) instance->pdata; if (evt->data.key.action == kDown_ANPKeyAction) {
if (obj->anim == NULL) { mUnichar = evt->data.key.unichar;
obj->anim = new BallAnimation(instance); gLogI.log(instance, kDebug_ANPLogType, "ball downkey event");
} browser->invalidaterect(instance, NULL);
obj->anim->draw(canvas);
} }
return 1;
default:
break;
}
return 0; // unknown or unhandled event
}

View File

@@ -23,18 +23,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "main.h" // for NPAPI definitions
#include "PluginObject.h" #include "PluginObject.h"
#include "android_npapi.h"
#ifndef pluginGraphics__DEFINED #ifndef pluginGraphics__DEFINED
#define pluginGraphics__DEFINED #define pluginGraphics__DEFINED
struct ANPBitmap; class BallAnimation : public SubPlugin {
struct ANPCanvas; public:
struct ANPRectI; BallAnimation(NPP inst);
virtual ~BallAnimation();
virtual void draw(ANPCanvas*);
virtual int16 handleEvent(const ANPEvent* evt);
private:
float m_x;
float m_y;
float m_dx;
float m_dy;
int32_t mUnichar;
ANPRectF m_oval;
ANPPaint* m_paint;
static const float SCALE = 0.1;
};
void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip);
void drawPlugin(NPP instance, ANPCanvas*);
uint32_t getMSecs(); uint32_t getMSecs();
#endif // pluginGraphics__DEFINED #endif // pluginGraphics__DEFINED

View File

@@ -0,0 +1,307 @@
/*
* Copyright 2008, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BackgroundPlugin.h"
#include "android_npapi.h"
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <string.h>
extern NPNetscapeFuncs* browser;
extern ANPBitmapInterfaceV0 gBitmapI;
extern ANPLogInterfaceV0 gLogI;
extern ANPCanvasInterfaceV0 gCanvasI;
extern ANPPaintInterfaceV0 gPaintI;
extern ANPPathInterfaceV0 gPathI;
extern ANPTypefaceInterfaceV0 gTypefaceI;
extern uint32_t getMSecs();
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
//#define LOG_ERROR(inst, string, params...) gLogI.log(inst, kError_ANPLogType, (log_prefix + string), inst, params)
///////////////////////////////////////////////////////////////////////////////
BackgroundPlugin::BackgroundPlugin(NPP inst) : SubPlugin(inst) {
m_paint = gPaintI.newPaint();
gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag);
gPaintI.setColor(m_paint, 0xFFFF0000);
gPaintI.setTextSize(m_paint, 16);
ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
gPaintI.setTypeface(m_paint, tf);
gTypefaceI.unref(tf);
//initialize variables
mFinishedStageOne = false;
mFinishedStageTwo = false;
mFinishedStageThree = false;
// test basic plugin functionality
test_logging(); // android logging
test_timers(); // plugin timers
test_bitmaps(); // android bitmaps
}
BackgroundPlugin::~BackgroundPlugin() {
}
void BackgroundPlugin::draw(ANPCanvas* canvas) {
gCanvasI.drawColor(canvas, 0xFFFFFFFF);
ANPFontMetrics fm;
gPaintI.getFontMetrics(m_paint, &fm);
gPaintI.setColor(m_paint, 0xFF0000FF);
const char c[] = "This is a background plugin.";
gCanvasI.drawText(canvas, c, sizeof(c)-1, 10, -fm.fTop, m_paint);
}
static void drawPlugin(SubPlugin* plugin, const ANPBitmap& bitmap, const ANPRectI& clip) {
ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
ANPRectF clipR;
clipR.left = clip.left;
clipR.top = clip.top;
clipR.right = clip.right;
clipR.bottom = clip.bottom;
gCanvasI.clipRect(canvas, &clipR);
plugin->draw(canvas);
gCanvasI.deleteCanvas(canvas);
}
int16 BackgroundPlugin::handleEvent(const ANPEvent* evt) {
NPP instance = this->inst();
switch (evt->eventType) {
case kDraw_ANPEventType:
switch (evt->data.draw.model) {
case kBitmap_ANPDrawingModel:
test_bitmap_transparency(evt);
drawPlugin(this, evt->data.draw.data.bitmap, evt->data.draw.clip);
return 1;
default:
break; // unknown drawing model
}
case kTouch_ANPEventType:
gLogI.log(instance, kError_ANPLogType, " ------ %p the plugin did not request touch events", instance);
case kKey_ANPEventType:
gLogI.log(instance, kError_ANPLogType, " ------ %p the plugin did not request key events", instance);
default:
break;
}
return 0; // unknown or unhandled event
}
///////////////////////////////////////////////////////////////////////////////
// LOGGING TESTS
///////////////////////////////////////////////////////////////////////////////
void BackgroundPlugin::test_logging() {
NPP instance = this->inst();
//LOG_ERROR(instance, " ------ %p Testing Log Error", instance);
gLogI.log(instance, kError_ANPLogType, " ------ %p Testing Log Error", instance);
gLogI.log(instance, kWarning_ANPLogType, " ------ %p Testing Log Warning", instance);
gLogI.log(instance, kDebug_ANPLogType, " ------ %p Testing Log Debug", instance);
}
///////////////////////////////////////////////////////////////////////////////
// TIMER TESTS
///////////////////////////////////////////////////////////////////////////////
#define TIMER_INTERVAL 50
static void timer_oneshot(NPP instance, uint32 timerID);
static void timer_repeat(NPP instance, uint32 timerID);
static void timer_neverfires(NPP instance, uint32 timerID);
static void timer_latency(NPP instance, uint32 timerID);
void BackgroundPlugin::test_timers() {
NPP instance = this->inst();
//Setup the testing counters
mTimerRepeatCount = 5;
mTimerLatencyCount = 5;
// test for bogus timerID
browser->unscheduletimer(instance, 999999);
// test one-shot
browser->scheduletimer(instance, 100, false, timer_oneshot);
// test repeat
browser->scheduletimer(instance, 50, true, timer_repeat);
// test timer latency
browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency);
mStartTime = mPrevTime = getMSecs();
// test unschedule immediately
uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires);
browser->unscheduletimer(instance, id);
// test double unschedule (should be no-op)
browser->unscheduletimer(instance, id);
}
static void timer_oneshot(NPP instance, uint32 timerID) {
gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n");
}
static void timer_repeat(NPP instance, uint32 timerID) {
BackgroundPlugin *obj = ((BackgroundPlugin*) ((PluginObject*) instance->pdata)->activePlugin);
gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n",
obj->mTimerRepeatCount);
if (--obj->mTimerRepeatCount == 0) {
browser->unscheduletimer(instance, timerID);
}
}
static void timer_neverfires(NPP instance, uint32 timerID) {
gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n");
}
static void timer_latency(NPP instance, uint32 timerID) {
BackgroundPlugin *obj = ((BackgroundPlugin*) ((PluginObject*) instance->pdata)->activePlugin);
obj->mTimerLatencyCurrentCount += 1;
uint32_t now = getMSecs();
uint32_t interval = now - obj->mPrevTime;
uint32_t dur = now - obj->mStartTime;
uint32_t expectedDur = obj->mTimerLatencyCurrentCount * TIMER_INTERVAL;
int32_t drift = dur - expectedDur;
int32_t avgDrift = drift / obj->mTimerLatencyCurrentCount;
obj->mPrevTime = now;
gLogI.log(instance, kDebug_ANPLogType,
"-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d avg %d\n",
obj->mTimerLatencyCurrentCount, interval, TIMER_INTERVAL, dur,
expectedDur, drift, avgDrift);
if (--obj->mTimerLatencyCount == 0) {
browser->unscheduletimer(instance, timerID);
}
}
///////////////////////////////////////////////////////////////////////////////
// BITMAP TESTS
///////////////////////////////////////////////////////////////////////////////
static void test_formats(NPP instance);
void BackgroundPlugin::test_bitmaps() {
test_formats(this->inst());
}
static void test_formats(NPP instance) {
// TODO pull names from enum in npapi instead of hardcoding them
static const struct {
ANPBitmapFormat fFormat;
const char* fName;
} gRecs[] = {
{ kUnknown_ANPBitmapFormat, "unknown" },
{ kRGBA_8888_ANPBitmapFormat, "8888" },
{ kRGB_565_ANPBitmapFormat, "565" },
};
ANPPixelPacking packing;
for (size_t i = 0; i < ARRAY_COUNT(gRecs); i++) {
if (gBitmapI.getPixelPacking(gRecs[i].fFormat, &packing)) {
gLogI.log(instance, kDebug_ANPLogType,
"pixel format [%d] %s has packing ARGB [%d %d] [%d %d] [%d %d] [%d %d]\n",
gRecs[i].fFormat, gRecs[i].fName,
packing.AShift, packing.ABits,
packing.RShift, packing.RBits,
packing.GShift, packing.GBits,
packing.BShift, packing.BBits);
} else {
gLogI.log(instance, kDebug_ANPLogType,
"pixel format [%d] %s has no packing\n",
gRecs[i].fFormat, gRecs[i].fName);
}
}
}
void BackgroundPlugin::test_bitmap_transparency(const ANPEvent* evt) {
NPP instance = this->inst();
// check default & set transparent
if (!mFinishedStageOne) {
gLogI.log(instance, kDebug_ANPLogType, "BEGIN: testing bitmap transparency");
//check to make sure it is not transparent
if (evt->data.draw.data.bitmap.format == kRGBA_8888_ANPBitmapFormat) {
gLogI.log(instance, kError_ANPLogType, "bitmap default format is transparent");
}
//make it transparent (any non-null value will set it to true)
bool value = true;
NPError err = browser->setvalue(instance, NPPVpluginTransparentBool, &value);
if (err != NPERR_NO_ERROR) {
gLogI.log(instance, kError_ANPLogType, "Error setting transparency.");
}
mFinishedStageOne = true;
browser->invalidaterect(instance, NULL);
}
// check transparent & set opaque
else if (!mFinishedStageTwo) {
//check to make sure it is transparent
if (evt->data.draw.data.bitmap.format != kRGBA_8888_ANPBitmapFormat) {
gLogI.log(instance, kError_ANPLogType, "bitmap did not change to transparent format");
}
//make it opaque
NPError err = browser->setvalue(instance, NPPVpluginTransparentBool, NULL);
if (err != NPERR_NO_ERROR) {
gLogI.log(instance, kError_ANPLogType, "Error setting transparency.");
}
mFinishedStageTwo = true;
}
// check opaque
else if (!mFinishedStageThree) {
//check to make sure it is not transparent
if (evt->data.draw.data.bitmap.format == kRGBA_8888_ANPBitmapFormat) {
gLogI.log(instance, kError_ANPLogType, "bitmap default format is transparent");
}
gLogI.log(instance, kDebug_ANPLogType, "END: testing bitmap transparency");
mFinishedStageThree = true;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2008, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "PluginObject.h"
#ifndef backgroundPlugin__DEFINED
#define backgroundPlugin__DEFINED
struct ANPCanvas;
struct ANPEvent;
struct ANPPaint;
class BackgroundPlugin : public SubPlugin {
public:
BackgroundPlugin(NPP inst);
virtual ~BackgroundPlugin();
virtual void draw(ANPCanvas*);
virtual int16 handleEvent(const ANPEvent* evt);
// Timer Testing Variables
uint32_t mStartTime;
uint32_t mPrevTime;
int mTimerRepeatCount;
int mTimerLatencyCount;
int mTimerLatencyCurrentCount;
// Bitmap Transparency Variables
bool mFinishedStageOne; // check default & set transparent
bool mFinishedStageTwo; // check transparent & set opaque
bool mFinishedStageThree; // check opaque
private:
ANPPaint* m_paint;
void test_logging();
void test_timers();
void test_bitmaps();
void test_bitmap_transparency(const ANPEvent* evt);
};
#endif // backgroundPlugin__DEFINED

View File

@@ -28,7 +28,8 @@
#include <stdio.h> #include <stdio.h>
#include "main.h" #include "main.h"
#include "PluginObject.h" #include "PluginObject.h"
#include "pluginGraphics.h" #include "AnimationPlugin.h"
#include "BackgroundPlugin.h"
#include "android_npapi.h" #include "android_npapi.h"
NPNetscapeFuncs* browser; NPNetscapeFuncs* browser;
@@ -128,12 +129,14 @@ void NP_Shutdown(void)
const char *NP_GetMIMEDescription(void) const char *NP_GetMIMEDescription(void)
{ {
return "application/x-testplugin:tst:Test plugin mimetype is application/x-testplugin"; return "application/x-testbrowserplugin:tst:Test plugin mimetype is application/x-testbrowserplugin";
} }
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
char* argn[], char* argv[], NPSavedData* saved) char* argn[], char* argv[], NPSavedData* saved)
{ {
/* BEGIN: STANDARD PLUGIN FRAMEWORK */
PluginObject *obj = NULL; PluginObject *obj = NULL;
// Scripting functions appeared in NPAPI version 14 // Scripting functions appeared in NPAPI version 14
@@ -142,89 +145,70 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
obj = static_cast<PluginObject*>(instance->pdata); obj = static_cast<PluginObject*>(instance->pdata);
bzero(obj, sizeof(*obj)); bzero(obj, sizeof(*obj));
} }
/* END: STANDARD PLUGIN FRAMEWORK */
uint32_t bits; // select the drawing model based on user input
NPError err = browser->getvalue(instance, kSupportedDrawingModel_ANPGetValue, &bits);
if (err) {
gLogI.log(instance, kError_ANPLogType, "supported model err %d", err);
return err;
}
ANPDrawingModel model = kBitmap_ANPDrawingModel; ANPDrawingModel model = kBitmap_ANPDrawingModel;
int count = argc; for (int i = 0; i < argc; i++) {
for (int i = 0; i < count; i++) {
if (!strcmp(argn[i], "DrawingModel")) { if (!strcmp(argn[i], "DrawingModel")) {
if (!strcmp(argv[i], "Bitmap")) { if (!strcmp(argv[i], "Bitmap")) {
model = kBitmap_ANPDrawingModel; model = kBitmap_ANPDrawingModel;
} }
if (!strcmp(argv[i], "Canvas")) { if (!strcmp(argv[i], "Canvas")) {
// obj->mTestTimers = true; //TODO support drawing on canvas instead of bitmap
} }
gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model); gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model);
break; break;
} }
} }
// comment this out to draw via bitmaps (the default) // comment this out to use the default model (bitmaps)
err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue, NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
reinterpret_cast<void*>(model)); reinterpret_cast<void*>(model));
if (err) { if (err) {
gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err); gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err);
}
return err; return err;
} }
// select the pluginType
for (int i = 0; i < argc; i++) {
if (!strcmp(argn[i], "PluginType")) {
if (!strcmp(argv[i], "Animation")) {
obj->pluginType = kAnimation_PluginType;
obj->activePlugin = new BallAnimation(instance);
}
else if (!strcmp(argv[i], "Audio")) {
obj->pluginType = kAudio_PluginType;
//TODO add audio here
}
else if (!strcmp(argv[i], "Background")) {
obj->pluginType = kBackground_PluginType;
obj->activePlugin = new BackgroundPlugin(instance);
}
gLogI.log(instance, kDebug_ANPLogType, "------ %p PluginType is %d", instance, obj->pluginType);
break;
}
}
// if no pluginType is specified then default to Animation
if (!obj->pluginType) {
obj->pluginType = kAnimation_PluginType;
obj->activePlugin = new BallAnimation(instance);
}
return NPERR_NO_ERROR;
}
NPError NPP_Destroy(NPP instance, NPSavedData** save) NPError NPP_Destroy(NPP instance, NPSavedData** save)
{ {
PluginObject *obj = (PluginObject*) instance->pdata; PluginObject *obj = (PluginObject*) instance->pdata;
delete obj->anim; delete obj->activePlugin;
gSoundI.deleteTrack(obj->track); gSoundI.deleteTrack(obj->track);
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
static void timer_oneshot(NPP instance, uint32 timerID) {
gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n");
}
static int gTimerRepeatCount;
static void timer_repeat(NPP instance, uint32 timerID) {
gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n",
gTimerRepeatCount);
if (--gTimerRepeatCount == 0) {
browser->unscheduletimer(instance, timerID);
}
}
static void timer_neverfires(NPP instance, uint32 timerID) {
gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n");
}
#define TIMER_INTERVAL 50
static void timer_latency(NPP instance, uint32 timerID) {
PluginObject *obj = (PluginObject*) instance->pdata;
obj->mTimerCount += 1;
uint32_t now = getMSecs();
uint32_t interval = now - obj->mPrevTime;
uint32_t dur = now - obj->mStartTime;
uint32_t expectedDur = obj->mTimerCount * TIMER_INTERVAL;
int32_t drift = dur - expectedDur;
int32_t aveDrift = drift / obj->mTimerCount;
obj->mPrevTime = now;
gLogI.log(instance, kDebug_ANPLogType,
"-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d ave %d\n",
obj->mTimerCount, interval, TIMER_INTERVAL, dur, expectedDur,
drift, aveDrift);
}
NPError NPP_SetWindow(NPP instance, NPWindow* window) NPError NPP_SetWindow(NPP instance, NPWindow* window)
{ {
PluginObject *obj = (PluginObject*) instance->pdata; PluginObject *obj = (PluginObject*) instance->pdata;
@@ -234,63 +218,11 @@ NPError NPP_SetWindow(NPP instance, NPWindow* window)
obj->window = window; obj->window = window;
} }
static bool gTestTimers;
if (!gTestTimers) {
gTestTimers = true;
// test for bogus timerID
browser->unscheduletimer(instance, 999999);
// test oneshot
browser->scheduletimer(instance, 100, false, timer_oneshot);
// test repeat
gTimerRepeatCount = 10;
browser->scheduletimer(instance, 50, true, timer_repeat);
// test unschedule immediately
uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires);
browser->unscheduletimer(instance, id);
// test double unschedlue (should be no-op)
browser->unscheduletimer(instance, id);
}
if (obj->mTestTimers) {
browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency);
obj->mStartTime = obj->mPrevTime = getMSecs();
obj->mTestTimers = false;
}
if (true) {
static const struct {
ANPBitmapFormat fFormat;
const char* fName;
} gRecs[] = {
{ kUnknown_ANPBitmapFormat, "unknown" },
{ kRGBA_8888_ANPBitmapFormat, "8888" },
{ kRGB_565_ANPBitmapFormat, "565" },
};
ANPPixelPacking packing;
for (size_t i = 0; i < ARRAY_COUNT(gRecs); i++) {
if (gBitmapI.getPixelPacking(gRecs[i].fFormat, &packing)) {
gLogI.log(instance, kDebug_ANPLogType,
"pixel format [%d] %s has packing ARGB [%d %d] [%d %d] [%d %d] [%d %d]\n",
gRecs[i].fFormat, gRecs[i].fName,
packing.AShift, packing.ABits,
packing.RShift, packing.RBits,
packing.GShift, packing.GBits,
packing.BShift, packing.BBits);
} else {
gLogI.log(instance, kDebug_ANPLogType,
"pixel format [%d] %s has no packing\n",
gRecs[i].fFormat, gRecs[i].fName);
}
}
}
browser->invalidaterect(instance, NULL); browser->invalidaterect(instance, NULL);
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
{ {
*stype = NP_ASFILEONLY; *stype = NP_ASFILEONLY;
@@ -318,7 +250,6 @@ void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
void NPP_Print(NPP instance, NPPrint* platformPrint) void NPP_Print(NPP instance, NPPrint* platformPrint)
{ {
} }
struct SoundPlay { struct SoundPlay {
@@ -370,14 +301,22 @@ int16 NPP_HandleEvent(NPP instance, void* event)
switch (evt->eventType) { switch (evt->eventType) {
case kDraw_ANPEventType: case kDraw_ANPEventType:
switch (evt->data.draw.model) {
case kBitmap_ANPDrawingModel: if (evt->data.draw.model == kBitmap_ANPDrawingModel) {
drawPlugin(instance, evt->data.draw.data.bitmap,
evt->data.draw.clip); static ANPBitmapFormat currentFormat = -1;
return 1; if (evt->data.draw.data.bitmap.format != currentFormat) {
default: currentFormat = evt->data.draw.data.bitmap.format;
break; // unknown drawing model gLogI.log(instance, kDebug_ANPLogType, "---- %p Draw (bitmap)"
" clip=%d,%d,%d,%d format=%d", instance,
evt->data.draw.clip.left,
evt->data.draw.clip.top,
evt->data.draw.clip.right,
evt->data.draw.clip.bottom,
evt->data.draw.data.bitmap.format);
} }
}
break;
case kKey_ANPEventType: case kKey_ANPEventType:
gLogI.log(instance, kDebug_ANPLogType, "---- %p Key action=%d" gLogI.log(instance, kDebug_ANPLogType, "---- %p Key action=%d"
@@ -388,11 +327,7 @@ int16 NPP_HandleEvent(NPP instance, void* event)
evt->data.key.unichar, evt->data.key.unichar,
evt->data.key.repeatCount, evt->data.key.repeatCount,
evt->data.key.modifiers); evt->data.key.modifiers);
if (evt->data.key.action == kDown_ANPKeyAction) { break;
obj->mUnichar = evt->data.key.unichar;
browser->invalidaterect(instance, NULL);
}
return 1;
case kLifecycle_ANPEventType: case kLifecycle_ANPEventType:
gLogI.log(instance, kDebug_ANPLogType, "---- %p Lifecycle action=%d", gLogI.log(instance, kDebug_ANPLogType, "---- %p Lifecycle action=%d",
@@ -422,8 +357,15 @@ int16 NPP_HandleEvent(NPP instance, void* event)
default: default:
break; break;
} }
if(!obj->activePlugin) {
gLogI.log(instance, kError_ANPLogType, "the active plugin is null.");
return 0; // unknown or unhandled event return 0; // unknown or unhandled event
} }
else {
return obj->activePlugin->handleEvent(evt);
}
}
void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
{ {

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB