1/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "AnimationPlugin.h"
27
28#include <math.h>
29#include <string.h>
30
31extern NPNetscapeFuncs*        browser;
32extern ANPLogInterfaceV0       gLogI;
33extern ANPCanvasInterfaceV0    gCanvasI;
34extern ANPPaintInterfaceV0     gPaintI;
35extern ANPPathInterfaceV0      gPathI;
36extern ANPSystemInterfaceV0    gSystemI;
37extern ANPWindowInterfaceV1    gWindowI;
38
39static uint16_t rnd16(float x, int inset) {
40    int ix = (int)roundf(x) + inset;
41    if (ix < 0) {
42        ix = 0;
43    }
44    return static_cast<uint16_t>(ix);
45}
46
47///////////////////////////////////////////////////////////////////////////////
48
49BallAnimation::BallAnimation(NPP inst) : SurfaceSubPlugin(inst) {
50    //register for touch events
51    ANPEventFlags flags = kTouch_ANPEventFlag;
52    NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
53    if (err != NPERR_NO_ERROR) {
54        gLogI.log(kError_ANPLogType, "Error selecting input events.");
55    }
56
57    gLogI.log(kError_ANPLogType, "Starting Rendering Thread");
58
59    //start a thread and do your drawing there
60    m_renderingThread = new AnimationThread(inst);
61    m_renderingThread->incStrong(inst);
62    m_renderingThread->run("AnimationThread");
63}
64
65BallAnimation::~BallAnimation() {
66    m_renderingThread->requestExitAndWait();
67    destroySurface();
68}
69
70bool BallAnimation::supportsDrawingModel(ANPDrawingModel model) {
71    return (model == kOpenGL_ANPDrawingModel);
72}
73
74jobject BallAnimation::getSurface() {
75
76    if (m_surface) {
77        return m_surface;
78    }
79
80    // load the appropriate java class and instantiate it
81    JNIEnv* env = NULL;
82    if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
83        gLogI.log(kError_ANPLogType, " ---- getSurface: failed to get env");
84        return NULL;
85    }
86
87    const char* className = "com.android.sampleplugin.AnimationSurface";
88    jclass fullScreenClass = gSystemI.loadJavaClass(inst(), className);
89
90    if(!fullScreenClass) {
91        gLogI.log(kError_ANPLogType, " ---- getSurface: failed to load class");
92        return NULL;
93    }
94
95    jmethodID constructor = env->GetMethodID(fullScreenClass, "<init>", "(Landroid/content/Context;)V");
96    jobject fullScreenSurface = env->NewObject(fullScreenClass, constructor, m_context);
97
98    if(!fullScreenSurface) {
99        gLogI.log(kError_ANPLogType, " ---- getSurface: failed to construct object");
100        return NULL;
101    }
102
103    gLogI.log(kError_ANPLogType, " ---- object %p", fullScreenSurface);
104
105    m_surface = env->NewGlobalRef(fullScreenSurface);
106    return m_surface;
107}
108
109void BallAnimation::destroySurface() {
110    JNIEnv* env = NULL;
111    if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
112        env->DeleteGlobalRef(m_surface);
113        m_surface = NULL;
114    }
115}
116
117void BallAnimation::showEntirePluginOnScreen() {
118    NPP instance = this->inst();
119    PluginObject *obj = (PluginObject*) instance->pdata;
120    NPWindow *window = obj->window;
121
122    // log the current visible rect
123    ANPRectI visibleRect = gWindowI.visibleRect(instance);
124    gLogI.log(kDebug_ANPLogType, "Current VisibleRect: (%d,%d,%d,%d)",
125            visibleRect.left, visibleRect.top, visibleRect.right, visibleRect.bottom);
126
127    ANPRectI visibleRects[1];
128
129    visibleRects[0].left = 0;
130    visibleRects[0].top = 0;
131    visibleRects[0].right = window->width;
132    visibleRects[0].bottom = window->height;
133
134    gWindowI.setVisibleRects(instance, visibleRects, 1);
135    gWindowI.clearVisibleRects(instance);
136}
137
138int16_t BallAnimation::handleEvent(const ANPEvent* evt) {
139    NPP instance = this->inst();
140
141    switch (evt->eventType) {
142        case kDraw_ANPEventType:
143            switch (evt->data.draw.model) {
144                case kOpenGL_ANPDrawingModel: {
145                    //send the width and height to the rendering thread
146                    int width = evt->data.draw.data.surface.width;
147                    int height = evt->data.draw.data.surface.height;
148                    gLogI.log(kError_ANPLogType, "New Dimensions (%d,%d)", width, height);
149                    m_renderingThread->setDimensions(width, height);
150                    return 1;
151                }
152                default:
153                    return 0;   // unknown drawing model
154            }
155        case kTouch_ANPEventType:
156             if (kDown_ANPTouchAction == evt->data.touch.action) {
157                 showEntirePluginOnScreen();
158             }
159            else if (kDoubleTap_ANPTouchAction == evt->data.touch.action) {
160                browser->geturl(inst(), "javascript:alert('Detected double tap event.')", 0);
161                gWindowI.requestFullScreen(inst());
162            }
163            return 1;
164        default:
165            break;
166    }
167    return 0;   // unknown or unhandled event
168}
169