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
31 extern NPNetscapeFuncs* browser;
32 extern ANPLogInterfaceV0 gLogI;
33 extern ANPCanvasInterfaceV0 gCanvasI;
34 extern ANPPaintInterfaceV0 gPaintI;
35 extern ANPPathInterfaceV0 gPathI;
36 extern ANPWindowInterfaceV0 gWindowI;
37
rnd16(float x,int inset)38 static uint16 rnd16(float x, int inset) {
39 int ix = (int)roundf(x) + inset;
40 if (ix < 0) {
41 ix = 0;
42 }
43 return static_cast<uint16>(ix);
44 }
45
inval(NPP instance,const ANPRectF & r,bool doAA)46 static void inval(NPP instance, const ANPRectF& r, bool doAA) {
47 const int inset = doAA ? -1 : 0;
48
49 NPRect inval;
50 inval.left = rnd16(r.left, inset);
51 inval.top = rnd16(r.top, inset);
52 inval.right = rnd16(r.right, -inset);
53 inval.bottom = rnd16(r.bottom, -inset);
54 browser->invalidaterect(instance, &inval);
55 }
56
bounce(float * x,float * dx,const float max)57 static void bounce(float* x, float* dx, const float max) {
58 *x += *dx;
59 if (*x < 0) {
60 *x = 0;
61 if (*dx < 0) {
62 *dx = -*dx;
63 }
64 } else if (*x > max) {
65 *x = max;
66 if (*dx > 0) {
67 *dx = -*dx;
68 }
69 }
70 }
71 ///////////////////////////////////////////////////////////////////////////////
72
BallAnimation(NPP inst)73 BallAnimation::BallAnimation(NPP inst) : SubPlugin(inst) {
74 m_x = m_y = 0;
75 m_dx = 7 * SCALE;
76 m_dy = 5 * SCALE;
77
78 memset(&m_oval, 0, sizeof(m_oval));
79
80 m_paint = gPaintI.newPaint();
81 gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag);
82 gPaintI.setColor(m_paint, 0xFFFF0000);
83
84 //register for touch events
85 ANPEventFlags flags = kTouch_ANPEventFlag;
86 NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
87 if (err != NPERR_NO_ERROR) {
88 gLogI.log(inst, kError_ANPLogType, "Error selecting input events.");
89 }
90 }
91
~BallAnimation()92 BallAnimation::~BallAnimation() {
93 gPaintI.deletePaint(m_paint);
94 }
95
supportsDrawingModel(ANPDrawingModel model)96 bool BallAnimation::supportsDrawingModel(ANPDrawingModel model) {
97 return (model == kBitmap_ANPDrawingModel);
98 }
99
drawPlugin(const ANPBitmap & bitmap,const ANPRectI & clip)100 void BallAnimation::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {
101
102 // create a canvas
103 ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
104
105 // clip the canvas
106 ANPRectF clipR;
107 clipR.left = clip.left;
108 clipR.top = clip.top;
109 clipR.right = clip.right;
110 clipR.bottom = clip.bottom;
111 gCanvasI.clipRect(canvas, &clipR);
112
113 // setup variables
114 PluginObject *obj = (PluginObject*) inst()->pdata;
115 const float OW = 20;
116 const float OH = 20;
117 const int W = obj->window->width;
118 const int H = obj->window->height;
119
120 // paint the canvas (using the path API)
121 gCanvasI.drawColor(canvas, 0xFFFFFFFF);
122 {
123 ANPPath* path = gPathI.newPath();
124
125 float cx = W * 0.5f;
126 float cy = H * 0.5f;
127 gPathI.moveTo(path, 0, 0);
128 gPathI.quadTo(path, cx, cy, W, 0);
129 gPathI.quadTo(path, cx, cy, W, H);
130 gPathI.quadTo(path, cx, cy, 0, H);
131 gPathI.quadTo(path, cx, cy, 0, 0);
132
133 gPaintI.setColor(m_paint, 0xFF0000FF);
134 gCanvasI.drawPath(canvas, path, m_paint);
135
136 ANPRectF bounds;
137 memset(&bounds, 0, sizeof(bounds));
138 gPathI.getBounds(path, &bounds);
139 gPathI.deletePath(path);
140 }
141
142 // draw the oval
143 inval(inst(), m_oval, true); // inval the old
144 m_oval.left = m_x;
145 m_oval.top = m_y;
146 m_oval.right = m_x + OW;
147 m_oval.bottom = m_y + OH;
148 inval(inst(), m_oval, true); // inval the new
149 gPaintI.setColor(m_paint, 0xFFFF0000);
150 gCanvasI.drawOval(canvas, &m_oval, m_paint);
151
152 // update the coordinates of the oval
153 bounce(&m_x, &m_dx, obj->window->width - OW);
154 bounce(&m_y, &m_dy, obj->window->height - OH);
155
156 // delete the canvas
157 gCanvasI.deleteCanvas(canvas);
158 }
159
showEntirePluginOnScreen()160 void BallAnimation::showEntirePluginOnScreen() {
161 NPP instance = this->inst();
162 PluginObject *obj = (PluginObject*) instance->pdata;
163 NPWindow *window = obj->window;
164
165 ANPRectI visibleRects[1];
166
167 visibleRects[0].left = 0;
168 visibleRects[0].top = 0;
169 visibleRects[0].right = window->width;
170 visibleRects[0].bottom = window->height;
171
172 gWindowI.setVisibleRects(instance, visibleRects, 1);
173 gWindowI.clearVisibleRects(instance);
174 }
175
handleEvent(const ANPEvent * evt)176 int16 BallAnimation::handleEvent(const ANPEvent* evt) {
177 NPP instance = this->inst();
178
179 switch (evt->eventType) {
180 case kDraw_ANPEventType:
181 switch (evt->data.draw.model) {
182 case kBitmap_ANPDrawingModel:
183 drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);
184 return 1;
185 default:
186 break; // unknown drawing model
187 }
188 case kTouch_ANPEventType:
189 if (kDown_ANPTouchAction == evt->data.touch.action) {
190 showEntirePluginOnScreen();
191 }
192 return 1;
193 default:
194 break;
195 }
196 return 0; // unknown or unhandled event
197 }
198