Restructuring the sample plugin and adding more tests.
This commit is contained in:
@@ -30,10 +30,13 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
main.cpp \
|
||||
PluginObject.cpp \
|
||||
pluginGraphics.cpp
|
||||
animation/AnimationPlugin.cpp \
|
||||
background/BackgroundPlugin.cpp
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/animation \
|
||||
$(LOCAL_PATH)/background \
|
||||
external/webkit/WebCore/bridge \
|
||||
external/webkit/WebCore/plugins \
|
||||
external/webkit/WebCore/platform/android/JavaVM \
|
||||
@@ -175,4 +175,3 @@ static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *cou
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,16 +34,18 @@
|
||||
#ifndef PluginObject__DEFINED
|
||||
#define PluginObject__DEFINED
|
||||
|
||||
#include "npapi.h"
|
||||
#include "main.h"
|
||||
|
||||
struct ANPEvent;
|
||||
struct ANPCanvas;
|
||||
struct ANPAudioTrack;
|
||||
|
||||
class Animation {
|
||||
class SubPlugin {
|
||||
public:
|
||||
Animation(NPP inst) : m_inst(inst) {}
|
||||
virtual ~Animation() {}
|
||||
SubPlugin(NPP inst) : m_inst(inst) {}
|
||||
virtual ~SubPlugin() {}
|
||||
virtual void draw(ANPCanvas*) = 0;
|
||||
virtual int16 handleEvent(const ANPEvent* evt) = 0;
|
||||
|
||||
NPP inst() const { return m_inst; }
|
||||
|
||||
@@ -51,18 +53,24 @@ private:
|
||||
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 {
|
||||
NPObject header;
|
||||
NPP npp;
|
||||
NPWindow* window;
|
||||
Animation* anim;
|
||||
ANPAudioTrack* track;
|
||||
int32_t mUnichar;
|
||||
|
||||
bool mTestTimers;
|
||||
uint32_t mStartTime;
|
||||
uint32_t mPrevTime;
|
||||
int mTimerCount;
|
||||
PluginType pluginType;
|
||||
SubPlugin* activePlugin;
|
||||
ANPAudioTrack* track;
|
||||
|
||||
} PluginObject;
|
||||
|
||||
NPClass *getPluginClass(void);
|
||||
@@ -23,9 +23,8 @@
|
||||
* 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 <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -63,6 +62,20 @@ static void inval(NPP instance, const ANPRectF& r, bool doAA) {
|
||||
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() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
@@ -71,24 +84,7 @@ uint32_t getMSecs() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BallAnimation : public Animation {
|
||||
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) {
|
||||
BallAnimation::BallAnimation(NPP inst) : SubPlugin(inst) {
|
||||
m_x = m_y = 0;
|
||||
m_dx = 7 * SCALE;
|
||||
m_dy = 5 * SCALE;
|
||||
@@ -103,6 +99,13 @@ BallAnimation::BallAnimation(NPP inst) : Animation(inst) {
|
||||
ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
|
||||
gPaintI.setTypeface(m_paint, 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() {
|
||||
@@ -173,38 +176,39 @@ void BallAnimation::draw(ANPCanvas* canvas) {
|
||||
bounce(&m_x, &m_dx, obj->window->width - OW);
|
||||
bounce(&m_y, &m_dy, obj->window->height - OH);
|
||||
|
||||
if (obj->mUnichar) {
|
||||
if (mUnichar) {
|
||||
ANPFontMetrics fm;
|
||||
gPaintI.getFontMetrics(m_paint, &fm);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int16 BallAnimation::handleEvent(const ANPEvent* evt) {
|
||||
NPP instance = this->inst();
|
||||
|
||||
void drawPlugin(NPP instance, 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);
|
||||
|
||||
drawPlugin(instance, canvas);
|
||||
|
||||
gCanvasI.deleteCanvas(canvas);
|
||||
}
|
||||
|
||||
void drawPlugin(NPP instance, ANPCanvas* canvas) {
|
||||
PluginObject *obj = (PluginObject*) instance->pdata;
|
||||
if (obj->anim == NULL) {
|
||||
obj->anim = new BallAnimation(instance);
|
||||
switch (evt->eventType) {
|
||||
case kDraw_ANPEventType:
|
||||
switch (evt->data.draw.model) {
|
||||
case kBitmap_ANPDrawingModel:
|
||||
drawPlugin(this, evt->data.draw.data.bitmap, evt->data.draw.clip);
|
||||
return 1;
|
||||
default:
|
||||
break; // unknown drawing model
|
||||
}
|
||||
obj->anim->draw(canvas);
|
||||
}
|
||||
|
||||
case kKey_ANPEventType:
|
||||
if (evt->data.key.action == kDown_ANPKeyAction) {
|
||||
mUnichar = evt->data.key.unichar;
|
||||
gLogI.log(instance, kDebug_ANPLogType, "ball downkey event");
|
||||
browser->invalidaterect(instance, NULL);
|
||||
}
|
||||
return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0; // unknown or unhandled event
|
||||
}
|
||||
@@ -23,18 +23,32 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "main.h" // for NPAPI definitions
|
||||
#include "PluginObject.h"
|
||||
#include "android_npapi.h"
|
||||
|
||||
#ifndef pluginGraphics__DEFINED
|
||||
#define pluginGraphics__DEFINED
|
||||
|
||||
struct ANPBitmap;
|
||||
struct ANPCanvas;
|
||||
struct ANPRectI;
|
||||
class BallAnimation : public SubPlugin {
|
||||
public:
|
||||
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();
|
||||
|
||||
#endif // pluginGraphics__DEFINED
|
||||
307
samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp
Normal file
307
samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
65
samples/BrowserPlugin/jni/background/BackgroundPlugin.h
Normal file
65
samples/BrowserPlugin/jni/background/BackgroundPlugin.h
Normal 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
|
||||
@@ -28,7 +28,8 @@
|
||||
#include <stdio.h>
|
||||
#include "main.h"
|
||||
#include "PluginObject.h"
|
||||
#include "pluginGraphics.h"
|
||||
#include "AnimationPlugin.h"
|
||||
#include "BackgroundPlugin.h"
|
||||
#include "android_npapi.h"
|
||||
|
||||
NPNetscapeFuncs* browser;
|
||||
@@ -128,12 +129,14 @@ void NP_Shutdown(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,
|
||||
char* argn[], char* argv[], NPSavedData* saved)
|
||||
{
|
||||
|
||||
/* BEGIN: STANDARD PLUGIN FRAMEWORK */
|
||||
PluginObject *obj = NULL;
|
||||
|
||||
// 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);
|
||||
bzero(obj, sizeof(*obj));
|
||||
}
|
||||
/* END: STANDARD PLUGIN FRAMEWORK */
|
||||
|
||||
uint32_t bits;
|
||||
NPError err = browser->getvalue(instance, kSupportedDrawingModel_ANPGetValue, &bits);
|
||||
if (err) {
|
||||
gLogI.log(instance, kError_ANPLogType, "supported model err %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// select the drawing model based on user input
|
||||
ANPDrawingModel model = kBitmap_ANPDrawingModel;
|
||||
|
||||
int count = argc;
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp(argn[i], "DrawingModel")) {
|
||||
if (!strcmp(argv[i], "Bitmap")) {
|
||||
model = kBitmap_ANPDrawingModel;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// comment this out to draw via bitmaps (the default)
|
||||
err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
|
||||
// comment this out to use the default model (bitmaps)
|
||||
NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
|
||||
reinterpret_cast<void*>(model));
|
||||
if (err) {
|
||||
gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, 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)
|
||||
{
|
||||
PluginObject *obj = (PluginObject*) instance->pdata;
|
||||
delete obj->anim;
|
||||
delete obj->activePlugin;
|
||||
gSoundI.deleteTrack(obj->track);
|
||||
|
||||
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)
|
||||
{
|
||||
PluginObject *obj = (PluginObject*) instance->pdata;
|
||||
@@ -234,63 +218,11 @@ NPError NPP_SetWindow(NPP instance, NPWindow* 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);
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
|
||||
{
|
||||
*stype = NP_ASFILEONLY;
|
||||
@@ -318,7 +250,6 @@ void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
|
||||
|
||||
void NPP_Print(NPP instance, NPPrint* platformPrint)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
struct SoundPlay {
|
||||
@@ -370,14 +301,22 @@ int16 NPP_HandleEvent(NPP instance, void* event)
|
||||
|
||||
switch (evt->eventType) {
|
||||
case kDraw_ANPEventType:
|
||||
switch (evt->data.draw.model) {
|
||||
case kBitmap_ANPDrawingModel:
|
||||
drawPlugin(instance, evt->data.draw.data.bitmap,
|
||||
evt->data.draw.clip);
|
||||
return 1;
|
||||
default:
|
||||
break; // unknown drawing model
|
||||
|
||||
if (evt->data.draw.model == kBitmap_ANPDrawingModel) {
|
||||
|
||||
static ANPBitmapFormat currentFormat = -1;
|
||||
if (evt->data.draw.data.bitmap.format != currentFormat) {
|
||||
currentFormat = evt->data.draw.data.bitmap.format;
|
||||
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:
|
||||
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.repeatCount,
|
||||
evt->data.key.modifiers);
|
||||
if (evt->data.key.action == kDown_ANPKeyAction) {
|
||||
obj->mUnichar = evt->data.key.unichar;
|
||||
browser->invalidaterect(instance, NULL);
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case kLifecycle_ANPEventType:
|
||||
gLogI.log(instance, kDebug_ANPLogType, "---- %p Lifecycle action=%d",
|
||||
@@ -422,7 +357,14 @@ int16 NPP_HandleEvent(NPP instance, void* event)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!obj->activePlugin) {
|
||||
gLogI.log(instance, kError_ANPLogType, "the active plugin is null.");
|
||||
return 0; // unknown or unhandled event
|
||||
}
|
||||
else {
|
||||
return obj->activePlugin->handleEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Reference in New Issue
Block a user