Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2009, 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 "PaintPlugin.h" |
| 27 | |
| 28 | #include <fcntl.h> |
| 29 | #include <math.h> |
| 30 | #include <string.h> |
| 31 | |
| 32 | extern NPNetscapeFuncs* browser; |
| 33 | extern ANPLogInterfaceV0 gLogI; |
| 34 | extern ANPCanvasInterfaceV0 gCanvasI; |
| 35 | extern ANPPaintInterfaceV0 gPaintI; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 36 | extern ANPPathInterfaceV0 gPathI; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 37 | extern ANPSurfaceInterfaceV0 gSurfaceI; |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 38 | extern ANPSystemInterfaceV0 gSystemI; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 39 | extern ANPTypefaceInterfaceV0 gTypefaceI; |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 40 | extern ANPWindowInterfaceV0 gWindowI; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 41 | |
| 42 | /////////////////////////////////////////////////////////////////////////////// |
| 43 | |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 44 | PaintPlugin::PaintPlugin(NPP inst) : SurfaceSubPlugin(inst) { |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 45 | |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 46 | m_isTouchActive = false; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 47 | m_isTouchCurrentInput = true; |
| 48 | m_activePaintColor = s_redColor; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 49 | |
| 50 | memset(&m_drawingSurface, 0, sizeof(m_drawingSurface)); |
| 51 | memset(&m_inputToggle, 0, sizeof(m_inputToggle)); |
| 52 | memset(&m_colorToggle, 0, sizeof(m_colorToggle)); |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 53 | memset(&m_fullScreenToggle, 0, sizeof(m_fullScreenToggle)); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 54 | memset(&m_clearSurface, 0, sizeof(m_clearSurface)); |
| 55 | |
| 56 | // initialize the drawing surface |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 57 | m_surface = NULL; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 58 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 59 | // initialize the path |
| 60 | m_touchPath = gPathI.newPath(); |
| 61 | if(!m_touchPath) |
Derek Sollenberger | e62ce17 | 2009-11-30 11:52:06 -0500 | [diff] [blame] | 62 | gLogI.log(kError_ANPLogType, "----%p Unable to create the touch path", inst); |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 63 | |
| 64 | // initialize the paint colors |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 65 | m_paintSurface = gPaintI.newPaint(); |
| 66 | gPaintI.setFlags(m_paintSurface, gPaintI.getFlags(m_paintSurface) | kAntiAlias_ANPPaintFlag); |
| 67 | gPaintI.setColor(m_paintSurface, 0xFFC0C0C0); |
| 68 | gPaintI.setTextSize(m_paintSurface, 18); |
| 69 | |
| 70 | m_paintButton = gPaintI.newPaint(); |
| 71 | gPaintI.setFlags(m_paintButton, gPaintI.getFlags(m_paintButton) | kAntiAlias_ANPPaintFlag); |
| 72 | gPaintI.setColor(m_paintButton, 0xFFA8A8A8); |
| 73 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 74 | // initialize the typeface (set the colors) |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 75 | ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle); |
| 76 | gPaintI.setTypeface(m_paintSurface, tf); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 77 | gTypefaceI.unref(tf); |
| 78 | |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 79 | //register for touch events |
| 80 | ANPEventFlags flags = kTouch_ANPEventFlag; |
| 81 | NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags); |
| 82 | if (err != NPERR_NO_ERROR) { |
Derek Sollenberger | e62ce17 | 2009-11-30 11:52:06 -0500 | [diff] [blame] | 83 | gLogI.log(kError_ANPLogType, "Error selecting input events."); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 84 | } |
| 85 | } |
| 86 | |
| 87 | PaintPlugin::~PaintPlugin() { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 88 | gPathI.deletePath(m_touchPath); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 89 | gPaintI.deletePaint(m_paintSurface); |
| 90 | gPaintI.deletePaint(m_paintButton); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 91 | |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 92 | setContext(NULL); |
| 93 | destroySurface(); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | ANPCanvas* PaintPlugin::getCanvas(ANPRectI* dirtyRect) { |
| 97 | |
| 98 | ANPBitmap bitmap; |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 99 | JNIEnv* env = NULL; |
Derek Sollenberger | b8947ee | 2009-10-05 14:40:18 -0400 | [diff] [blame] | 100 | if (!m_surface || gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK || |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 101 | !gSurfaceI.lock(env, m_surface, &bitmap, dirtyRect)) { |
| 102 | return NULL; |
| 103 | } |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 104 | |
| 105 | ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap); |
| 106 | |
| 107 | // clip the canvas to the dirty rect b/c the surface is only required to |
| 108 | // copy a minimum of the dirty rect and may copy more. The clipped canvas |
| 109 | // however will never write to pixels outside of the clipped area. |
| 110 | if (dirtyRect) { |
| 111 | ANPRectF clipR; |
| 112 | clipR.left = dirtyRect->left; |
| 113 | clipR.top = dirtyRect->top; |
| 114 | clipR.right = dirtyRect->right; |
| 115 | clipR.bottom = dirtyRect->bottom; |
| 116 | gCanvasI.clipRect(canvas, &clipR); |
| 117 | } |
| 118 | |
| 119 | return canvas; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | ANPCanvas* PaintPlugin::getCanvas(ANPRectF* dirtyRect) { |
| 123 | |
| 124 | ANPRectI newRect; |
| 125 | newRect.left = (int) dirtyRect->left; |
| 126 | newRect.top = (int) dirtyRect->top; |
| 127 | newRect.right = (int) dirtyRect->right; |
| 128 | newRect.bottom = (int) dirtyRect->bottom; |
| 129 | |
| 130 | return getCanvas(&newRect); |
| 131 | } |
| 132 | |
| 133 | void PaintPlugin::releaseCanvas(ANPCanvas* canvas) { |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 134 | JNIEnv* env = NULL; |
Derek Sollenberger | b8947ee | 2009-10-05 14:40:18 -0400 | [diff] [blame] | 135 | if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 136 | gSurfaceI.unlock(env, m_surface); |
| 137 | } |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 138 | gCanvasI.deleteCanvas(canvas); |
| 139 | } |
| 140 | |
| 141 | void PaintPlugin::drawCleanPlugin(ANPCanvas* canvas) { |
| 142 | NPP instance = this->inst(); |
| 143 | PluginObject *obj = (PluginObject*) instance->pdata; |
| 144 | |
| 145 | // if no canvas get a locked canvas |
| 146 | if (!canvas) |
| 147 | canvas = getCanvas(); |
| 148 | |
| 149 | if (!canvas) |
| 150 | return; |
| 151 | |
| 152 | const float buttonWidth = 60; |
| 153 | const float buttonHeight = 30; |
| 154 | const int W = obj->window->width; |
| 155 | const int H = obj->window->height; |
| 156 | |
| 157 | // color the plugin canvas |
| 158 | gCanvasI.drawColor(canvas, 0xFFCDCDCD); |
| 159 | |
| 160 | // get font metrics |
| 161 | ANPFontMetrics fontMetrics; |
| 162 | gPaintI.getFontMetrics(m_paintSurface, &fontMetrics); |
| 163 | |
| 164 | // draw the input toggle button |
| 165 | m_inputToggle.left = 5; |
| 166 | m_inputToggle.top = H - buttonHeight - 5; |
| 167 | m_inputToggle.right = m_inputToggle.left + buttonWidth; |
| 168 | m_inputToggle.bottom = m_inputToggle.top + buttonHeight; |
| 169 | gCanvasI.drawRect(canvas, &m_inputToggle, m_paintButton); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 170 | const char* inputText = m_isTouchCurrentInput ? "Touch" : "Mouse"; |
| 171 | gCanvasI.drawText(canvas, inputText, strlen(inputText), m_inputToggle.left + 5, |
| 172 | m_inputToggle.top - fontMetrics.fTop, m_paintSurface); |
| 173 | |
| 174 | // draw the color selector button |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 175 | m_colorToggle.left = (W/3) - (buttonWidth/2); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 176 | m_colorToggle.top = H - buttonHeight - 5; |
| 177 | m_colorToggle.right = m_colorToggle.left + buttonWidth; |
| 178 | m_colorToggle.bottom = m_colorToggle.top + buttonHeight; |
| 179 | gCanvasI.drawRect(canvas, &m_colorToggle, m_paintButton); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 180 | const char* colorText = getColorText(); |
| 181 | gCanvasI.drawText(canvas, colorText, strlen(colorText), m_colorToggle.left + 5, |
| 182 | m_colorToggle.top - fontMetrics.fTop, m_paintSurface); |
| 183 | |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 184 | // draw the full-screen toggle button |
| 185 | m_fullScreenToggle.left = ((W*2)/3) - (buttonWidth/2); |
| 186 | m_fullScreenToggle.top = H - buttonHeight - 5; |
| 187 | m_fullScreenToggle.right = m_fullScreenToggle.left + buttonWidth; |
| 188 | m_fullScreenToggle.bottom = m_fullScreenToggle.top + buttonHeight; |
| 189 | gCanvasI.drawRect(canvas, &m_fullScreenToggle, m_paintButton); |
| 190 | const char* fullScreenText = "Full"; |
| 191 | gCanvasI.drawText(canvas, fullScreenText, strlen(fullScreenText), |
| 192 | m_fullScreenToggle.left + 5, |
| 193 | m_fullScreenToggle.top - fontMetrics.fTop, m_paintSurface); |
| 194 | |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 195 | // draw the clear canvas button |
| 196 | m_clearSurface.left = W - buttonWidth - 5; |
| 197 | m_clearSurface.top = H - buttonHeight - 5; |
| 198 | m_clearSurface.right = m_clearSurface.left + buttonWidth; |
| 199 | m_clearSurface.bottom = m_clearSurface.top + buttonHeight; |
| 200 | gCanvasI.drawRect(canvas, &m_clearSurface, m_paintButton); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 201 | const char* clearText = "Clear"; |
| 202 | gCanvasI.drawText(canvas, clearText, strlen(clearText), m_clearSurface.left + 5, |
| 203 | m_clearSurface.top - fontMetrics.fTop, m_paintSurface); |
| 204 | |
| 205 | // draw the drawing surface box (5 px from the edge) |
| 206 | m_drawingSurface.left = 5; |
| 207 | m_drawingSurface.top = 5; |
| 208 | m_drawingSurface.right = W - 5; |
| 209 | m_drawingSurface.bottom = m_colorToggle.top - 5; |
| 210 | gCanvasI.drawRect(canvas, &m_drawingSurface, m_paintSurface); |
| 211 | |
| 212 | // release the canvas |
| 213 | releaseCanvas(canvas); |
| 214 | } |
| 215 | |
| 216 | const char* PaintPlugin::getColorText() { |
| 217 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 218 | if (m_activePaintColor == s_blueColor) |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 219 | return "Blue"; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 220 | else if (m_activePaintColor == s_greenColor) |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 221 | return "Green"; |
| 222 | else |
| 223 | return "Red"; |
| 224 | } |
| 225 | |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 226 | jobject PaintPlugin::getSurface() { |
| 227 | if (m_surface) { |
| 228 | return m_surface; |
| 229 | } |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 230 | |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 231 | // load the appropriate java class and instantiate it |
| 232 | JNIEnv* env = NULL; |
| 233 | if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { |
| 234 | gLogI.log(kError_ANPLogType, " ---- getSurface: failed to get env"); |
| 235 | return NULL; |
| 236 | } |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 237 | |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 238 | const char* className = "com.android.sampleplugin.PaintSurface"; |
| 239 | jclass paintClass = gSystemI.loadJavaClass(inst(), className); |
| 240 | |
| 241 | if(!paintClass) { |
| 242 | gLogI.log(kError_ANPLogType, " ---- getSurface: failed to load class"); |
| 243 | return NULL; |
| 244 | } |
| 245 | |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 246 | PluginObject *obj = (PluginObject*) inst()->pdata; |
| 247 | const int pW = obj->window->width; |
| 248 | const int pH = obj->window->height; |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 249 | |
| 250 | jmethodID constructor = env->GetMethodID(paintClass, "<init>", "(Landroid/content/Context;III)V"); |
| 251 | jobject paintSurface = env->NewObject(paintClass, constructor, m_context, (int)inst(), pW, pH); |
| 252 | |
| 253 | if(!paintSurface) { |
| 254 | gLogI.log(kError_ANPLogType, " ---- getSurface: failed to construct object"); |
| 255 | return NULL; |
| 256 | } |
| 257 | |
| 258 | m_surface = env->NewGlobalRef(paintSurface); |
| 259 | return m_surface; |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 260 | } |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 261 | |
| 262 | void PaintPlugin::destroySurface() { |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 263 | JNIEnv* env = NULL; |
Derek Sollenberger | b8947ee | 2009-10-05 14:40:18 -0400 | [diff] [blame] | 264 | if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 265 | |
| 266 | // detach the native code from the object |
| 267 | jclass javaClass = env->GetObjectClass(m_surface); |
| 268 | jmethodID invalMethod = env->GetMethodID(javaClass, "invalidateNPP", "()V"); |
| 269 | env->CallVoidMethod(m_surface, invalMethod); |
| 270 | |
Derek Sollenberger | 08581f1 | 2009-09-08 18:36:29 -0400 | [diff] [blame] | 271 | env->DeleteGlobalRef(m_surface); |
| 272 | m_surface = NULL; |
| 273 | } |
| 274 | } |
| 275 | |
Ben Murdoch | 3b6f45d | 2010-05-12 14:09:26 +0100 | [diff] [blame] | 276 | int16_t PaintPlugin::handleEvent(const ANPEvent* evt) { |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 277 | switch (evt->eventType) { |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 278 | case kTouch_ANPEventType: { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 279 | float x = (float) evt->data.touch.x; |
| 280 | float y = (float) evt->data.touch.y; |
| 281 | if (kDown_ANPTouchAction == evt->data.touch.action && m_isTouchCurrentInput) { |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 282 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 283 | ANPRectF* rect = validTouch(evt->data.touch.x, evt->data.touch.y); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 284 | if(rect == &m_drawingSurface) { |
| 285 | m_isTouchActive = true; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 286 | gPathI.moveTo(m_touchPath, x, y); |
| 287 | paintTouch(); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 288 | return 1; |
| 289 | } |
| 290 | |
| 291 | } else if (kMove_ANPTouchAction == evt->data.touch.action && m_isTouchActive) { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 292 | gPathI.lineTo(m_touchPath, x, y); |
| 293 | paintTouch(); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 294 | return 1; |
| 295 | } else if (kUp_ANPTouchAction == evt->data.touch.action && m_isTouchActive) { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 296 | gPathI.lineTo(m_touchPath, x, y); |
| 297 | paintTouch(); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 298 | m_isTouchActive = false; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 299 | gPathI.reset(m_touchPath); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 300 | return 1; |
| 301 | } else if (kCancel_ANPTouchAction == evt->data.touch.action) { |
| 302 | m_isTouchActive = false; |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 303 | gPathI.reset(m_touchPath); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 304 | return 1; |
Bart Sears | 33638a7 | 2010-03-15 15:52:54 -0700 | [diff] [blame] | 305 | } else if (kDoubleTap_ANPTouchAction == evt->data.touch.action) { |
| 306 | gWindowI.requestCenterFitZoom(inst()); |
| 307 | return 1; |
Grace Kloba | 103e576 | 2010-03-12 18:35:23 -0800 | [diff] [blame] | 308 | |
Bart Sears | 33638a7 | 2010-03-15 15:52:54 -0700 | [diff] [blame] | 309 | } |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 310 | break; |
| 311 | } |
| 312 | case kMouse_ANPEventType: { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 313 | |
| 314 | if (m_isTouchActive) |
Derek Sollenberger | e62ce17 | 2009-11-30 11:52:06 -0500 | [diff] [blame] | 315 | gLogI.log(kError_ANPLogType, "----%p Received unintended mouse event", inst()); |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 316 | |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 317 | if (kDown_ANPMouseAction == evt->data.mouse.action) { |
| 318 | ANPRectF* rect = validTouch(evt->data.mouse.x, evt->data.mouse.y); |
| 319 | if (rect == &m_drawingSurface) |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 320 | paintMouse(evt->data.mouse.x, evt->data.mouse.y); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 321 | else if (rect == &m_inputToggle) |
| 322 | toggleInputMethod(); |
| 323 | else if (rect == &m_colorToggle) |
| 324 | togglePaintColor(); |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 325 | else if (rect == &m_fullScreenToggle) |
| 326 | gWindowI.requestFullScreen(inst()); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 327 | else if (rect == &m_clearSurface) |
| 328 | drawCleanPlugin(); |
| 329 | } |
| 330 | return 1; |
| 331 | } |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 332 | case kCustom_ANPEventType: { |
| 333 | |
| 334 | switch (evt->data.other[0]) { |
| 335 | case kSurfaceCreated_CustomEvent: |
| 336 | gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceCreated"); |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 337 | /* The second draw call is added to cover up a problem in this |
| 338 | plugin and is not a recommended usage pattern. This plugin |
| 339 | does not correctly make partial updates to the double |
| 340 | buffered surface and this second call hides that problem. |
| 341 | */ |
| 342 | drawCleanPlugin(); |
Derek Sollenberger | d53b56d | 2010-01-11 12:31:49 -0500 | [diff] [blame] | 343 | drawCleanPlugin(); |
| 344 | break; |
| 345 | case kSurfaceChanged_CustomEvent: { |
| 346 | gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceChanged"); |
| 347 | |
| 348 | int width = evt->data.other[1]; |
| 349 | int height = evt->data.other[2]; |
| 350 | |
| 351 | PluginObject *obj = (PluginObject*) inst()->pdata; |
| 352 | const int pW = obj->window->width; |
| 353 | const int pH = obj->window->height; |
| 354 | // compare to the plugin's surface dimensions |
| 355 | if (pW != width || pH != height) |
| 356 | gLogI.log(kError_ANPLogType, |
| 357 | "----%p Invalid Surface Dimensions (%d,%d):(%d,%d)", |
| 358 | inst(), pW, pH, width, height); |
| 359 | break; |
| 360 | } |
| 361 | case kSurfaceDestroyed_CustomEvent: |
| 362 | gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceDestroyed"); |
| 363 | break; |
| 364 | } |
| 365 | break; // end KCustom_ANPEventType |
| 366 | } |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 367 | default: |
| 368 | break; |
| 369 | } |
| 370 | return 0; // unknown or unhandled event |
| 371 | } |
| 372 | |
| 373 | ANPRectF* PaintPlugin::validTouch(int x, int y) { |
| 374 | |
| 375 | //convert to float |
| 376 | float fx = (int) x; |
| 377 | float fy = (int) y; |
| 378 | |
| 379 | if (fx > m_drawingSurface.left && fx < m_drawingSurface.right && fy > m_drawingSurface.top && fy < m_drawingSurface.bottom) |
| 380 | return &m_drawingSurface; |
| 381 | else if (fx > m_inputToggle.left && fx < m_inputToggle.right && fy > m_inputToggle.top && fy < m_inputToggle.bottom) |
| 382 | return &m_inputToggle; |
| 383 | else if (fx > m_colorToggle.left && fx < m_colorToggle.right && fy > m_colorToggle.top && fy < m_colorToggle.bottom) |
| 384 | return &m_colorToggle; |
Derek Sollenberger | 7364d2b | 2010-03-01 08:18:02 -0500 | [diff] [blame] | 385 | else if (fx > m_fullScreenToggle.left && fx < m_fullScreenToggle.right && fy > m_fullScreenToggle.top && fy < m_fullScreenToggle.bottom) |
| 386 | return &m_fullScreenToggle; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 387 | else if (fx > m_clearSurface.left && fx < m_clearSurface.right && fy > m_clearSurface.top && fy < m_clearSurface.bottom) |
| 388 | return &m_clearSurface; |
| 389 | else |
| 390 | return NULL; |
| 391 | } |
| 392 | |
| 393 | void PaintPlugin::toggleInputMethod() { |
| 394 | m_isTouchCurrentInput = !m_isTouchCurrentInput; |
| 395 | |
| 396 | // lock only the input toggle and redraw the canvas |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 397 | ANPCanvas* lockedCanvas = getCanvas(&m_inputToggle); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 398 | drawCleanPlugin(lockedCanvas); |
| 399 | } |
| 400 | |
| 401 | void PaintPlugin::togglePaintColor() { |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 402 | if (m_activePaintColor == s_blueColor) |
| 403 | m_activePaintColor = s_redColor; |
| 404 | else if (m_activePaintColor == s_greenColor) |
| 405 | m_activePaintColor = s_blueColor; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 406 | else |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 407 | m_activePaintColor = s_greenColor; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 408 | |
| 409 | // lock only the color toggle and redraw the canvas |
| 410 | ANPCanvas* lockedCanvas = getCanvas(&m_colorToggle); |
| 411 | drawCleanPlugin(lockedCanvas); |
| 412 | } |
| 413 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 414 | void PaintPlugin::paintMouse(int x, int y) { |
| 415 | //TODO do not paint outside the drawing surface |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 416 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 417 | //create the paint color |
| 418 | ANPPaint* fillPaint = gPaintI.newPaint(); |
| 419 | gPaintI.setFlags(fillPaint, gPaintI.getFlags(fillPaint) | kAntiAlias_ANPPaintFlag); |
| 420 | gPaintI.setStyle(fillPaint, kFill_ANPPaintStyle); |
| 421 | gPaintI.setColor(fillPaint, m_activePaintColor); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 422 | |
| 423 | // handle the simple "mouse" paint (draw a point) |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 424 | ANPRectF point; |
| 425 | point.left = (float) x-3; |
| 426 | point.top = (float) y-3; |
| 427 | point.right = (float) x+3; |
| 428 | point.bottom = (float) y+3; |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 429 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 430 | // get a canvas that is only locked around the point and draw it |
| 431 | ANPCanvas* canvas = getCanvas(&point); |
| 432 | gCanvasI.drawOval(canvas, &point, fillPaint); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 433 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 434 | // clean up |
| 435 | releaseCanvas(canvas); |
| 436 | gPaintI.deletePaint(fillPaint); |
| 437 | } |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 438 | |
Derek Sollenberger | b6f5cd2 | 2009-07-28 14:09:50 -0400 | [diff] [blame] | 439 | void PaintPlugin::paintTouch() { |
| 440 | //TODO do not paint outside the drawing surface |
| 441 | |
| 442 | //create the paint color |
| 443 | ANPPaint* strokePaint = gPaintI.newPaint(); |
| 444 | gPaintI.setFlags(strokePaint, gPaintI.getFlags(strokePaint) | kAntiAlias_ANPPaintFlag); |
| 445 | gPaintI.setColor(strokePaint, m_activePaintColor); |
| 446 | gPaintI.setStyle(strokePaint, kStroke_ANPPaintStyle); |
| 447 | gPaintI.setStrokeWidth(strokePaint, 6.0); |
| 448 | gPaintI.setStrokeCap(strokePaint, kRound_ANPPaintCap); |
| 449 | gPaintI.setStrokeJoin(strokePaint, kRound_ANPPaintJoin); |
| 450 | |
| 451 | // handle the complex "touch" paint (draw a line) |
| 452 | ANPRectF bounds; |
| 453 | gPathI.getBounds(m_touchPath, &bounds); |
| 454 | |
| 455 | // get a canvas that is only locked around the point and draw the path |
| 456 | ANPCanvas* canvas = getCanvas(&bounds); |
| 457 | gCanvasI.drawPath(canvas, m_touchPath, strokePaint); |
| 458 | |
| 459 | // clean up |
| 460 | releaseCanvas(canvas); |
| 461 | gPaintI.deletePaint(strokePaint); |
Derek Sollenberger | 4fb83e6 | 2009-07-27 16:40:13 -0400 | [diff] [blame] | 462 | } |