diff options
Diffstat (limited to 'samples/BrowserPlugin/jni/paint/PaintPlugin.cpp')
| -rw-r--r-- | samples/BrowserPlugin/jni/paint/PaintPlugin.cpp | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp b/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp new file mode 100644 index 000000000..cad0bae5f --- /dev/null +++ b/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp @@ -0,0 +1,341 @@ +/* + * Copyright 2009, 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 "PaintPlugin.h" + +#include <fcntl.h> +#include <math.h> +#include <string.h> + +extern NPNetscapeFuncs* browser; +extern ANPLogInterfaceV0 gLogI; +extern ANPCanvasInterfaceV0 gCanvasI; +extern ANPPaintInterfaceV0 gPaintI; +extern ANPSurfaceInterfaceV0 gSurfaceI; +extern ANPTypefaceInterfaceV0 gTypefaceI; + +/////////////////////////////////////////////////////////////////////////////// + +PaintPlugin::PaintPlugin(NPP inst) : SubPlugin(inst) { + + m_isTouchCurrentInput = true; + m_isTouchActive = false; + m_prevX = m_prevY = 0; + + memset(&m_drawingSurface, 0, sizeof(m_drawingSurface)); + memset(&m_inputToggle, 0, sizeof(m_inputToggle)); + memset(&m_colorToggle, 0, sizeof(m_colorToggle)); + memset(&m_clearSurface, 0, sizeof(m_clearSurface)); + + // initialize the drawing surface + m_surfaceReady = false; + m_surface = gSurfaceI.newSurface(inst, kRGBA_ANPSurfaceType); + if(!m_surface) + gLogI.log(inst, kError_ANPLogType, "----%p Unable to create RGBA surface", inst); + + m_paintSurface = gPaintI.newPaint(); + gPaintI.setFlags(m_paintSurface, gPaintI.getFlags(m_paintSurface) | kAntiAlias_ANPPaintFlag); + gPaintI.setColor(m_paintSurface, 0xFFC0C0C0); + gPaintI.setTextSize(m_paintSurface, 18); + + m_paintButton = gPaintI.newPaint(); + gPaintI.setFlags(m_paintButton, gPaintI.getFlags(m_paintButton) | kAntiAlias_ANPPaintFlag); + gPaintI.setColor(m_paintButton, 0xFFA8A8A8); + + m_paintBlue = gPaintI.newPaint(); + gPaintI.setFlags(m_paintBlue, gPaintI.getFlags(m_paintBlue) | kAntiAlias_ANPPaintFlag); + gPaintI.setColor(m_paintBlue, 0xFF0000FF); + gPaintI.setTextSize(m_paintBlue, 18); + + m_paintGreen = gPaintI.newPaint(); + gPaintI.setFlags(m_paintGreen, gPaintI.getFlags(m_paintGreen) | kAntiAlias_ANPPaintFlag); + gPaintI.setColor(m_paintGreen, 0xFF00FF00); + gPaintI.setTextSize(m_paintGreen, 18); + + m_paintRed = gPaintI.newPaint(); + gPaintI.setFlags(m_paintRed, gPaintI.getFlags(m_paintRed) | kAntiAlias_ANPPaintFlag); + gPaintI.setColor(m_paintRed, 0xFFFF0000); + gPaintI.setTextSize(m_paintRed, 18); + + ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle); + gPaintI.setTypeface(m_paintSurface, tf); + gPaintI.setTypeface(m_paintBlue, tf); + gPaintI.setTypeface(m_paintGreen, tf); + gPaintI.setTypeface(m_paintRed, tf); + gTypefaceI.unref(tf); + + // set the default paint color + m_activePaint = m_paintRed; + + //register for touch events + ANPEventFlags flags = kTouch_ANPEventFlag; + NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags); + if (err != NPERR_NO_ERROR) { + gLogI.log(inst, kError_ANPLogType, "Error selecting input events."); + } +} + +PaintPlugin::~PaintPlugin() { + gPaintI.deletePaint(m_paintSurface); + gPaintI.deletePaint(m_paintButton); + gPaintI.deletePaint(m_paintBlue); + gPaintI.deletePaint(m_paintGreen); + gPaintI.deletePaint(m_paintRed); +} + +bool PaintPlugin::supportsDrawingModel(ANPDrawingModel model) { + return (model == kSurface_ANPDrawingModel); +} + +ANPCanvas* PaintPlugin::getCanvas(ANPRectI* dirtyRect) { + + ANPBitmap bitmap; + if (!m_surfaceReady || !gSurfaceI.lock(m_surface, &bitmap, dirtyRect)) + return NULL; + return gCanvasI.newCanvas(&bitmap); +} + +ANPCanvas* PaintPlugin::getCanvas(ANPRectF* dirtyRect) { + + ANPRectI newRect; + newRect.left = (int) dirtyRect->left; + newRect.top = (int) dirtyRect->top; + newRect.right = (int) dirtyRect->right; + newRect.bottom = (int) dirtyRect->bottom; + + return getCanvas(&newRect); +} + +void PaintPlugin::releaseCanvas(ANPCanvas* canvas) { + gSurfaceI.unlock(m_surface); + gCanvasI.deleteCanvas(canvas); +} + +void PaintPlugin::drawCleanPlugin(ANPCanvas* canvas) { + NPP instance = this->inst(); + PluginObject *obj = (PluginObject*) instance->pdata; + + // if no canvas get a locked canvas + if (!canvas) + canvas = getCanvas(); + + if (!canvas) + return; + + const float buttonWidth = 60; + const float buttonHeight = 30; + const int W = obj->window->width; + const int H = obj->window->height; + + // color the plugin canvas + gCanvasI.drawColor(canvas, 0xFFCDCDCD); + + // get font metrics + ANPFontMetrics fontMetrics; + gPaintI.getFontMetrics(m_paintSurface, &fontMetrics); + + // draw the input toggle button + m_inputToggle.left = 5; + m_inputToggle.top = H - buttonHeight - 5; + m_inputToggle.right = m_inputToggle.left + buttonWidth; + m_inputToggle.bottom = m_inputToggle.top + buttonHeight; + gCanvasI.drawRect(canvas, &m_inputToggle, m_paintButton); + // draw the play box (under track box) + const char* inputText = m_isTouchCurrentInput ? "Touch" : "Mouse"; + gCanvasI.drawText(canvas, inputText, strlen(inputText), m_inputToggle.left + 5, + m_inputToggle.top - fontMetrics.fTop, m_paintSurface); + + // draw the color selector button + m_colorToggle.left = (W/2) - (buttonWidth/2); + m_colorToggle.top = H - buttonHeight - 5; + m_colorToggle.right = m_colorToggle.left + buttonWidth; + m_colorToggle.bottom = m_colorToggle.top + buttonHeight; + gCanvasI.drawRect(canvas, &m_colorToggle, m_paintButton); + // draw the play box (under track box) + const char* colorText = getColorText(); + gCanvasI.drawText(canvas, colorText, strlen(colorText), m_colorToggle.left + 5, + m_colorToggle.top - fontMetrics.fTop, m_paintSurface); + + // draw the clear canvas button + m_clearSurface.left = W - buttonWidth - 5; + m_clearSurface.top = H - buttonHeight - 5; + m_clearSurface.right = m_clearSurface.left + buttonWidth; + m_clearSurface.bottom = m_clearSurface.top + buttonHeight; + gCanvasI.drawRect(canvas, &m_clearSurface, m_paintButton); + // draw the play box (under track box) + const char* clearText = "Clear"; + gCanvasI.drawText(canvas, clearText, strlen(clearText), m_clearSurface.left + 5, + m_clearSurface.top - fontMetrics.fTop, m_paintSurface); + + // draw the drawing surface box (5 px from the edge) + m_drawingSurface.left = 5; + m_drawingSurface.top = 5; + m_drawingSurface.right = W - 5; + m_drawingSurface.bottom = m_colorToggle.top - 5; + gCanvasI.drawRect(canvas, &m_drawingSurface, m_paintSurface); + + // release the canvas + releaseCanvas(canvas); +} + +const char* PaintPlugin::getColorText() { + + if (m_activePaint == m_paintBlue) + return "Blue"; + else if (m_activePaint == m_paintGreen) + return "Green"; + else + return "Red"; +} + +int16 PaintPlugin::handleEvent(const ANPEvent* evt) { + NPP instance = this->inst(); + + switch (evt->eventType) { + case kSurface_ANPEventType: + switch (evt->data.surface.action) { + case kCreated_ANPSurfaceAction: + m_surfaceReady = true; + drawCleanPlugin(); + return 1; + case kDestroyed_ANPSurfaceAction: + m_surfaceReady = false; + return 1; + } + break; + + case kTouch_ANPEventType: { + int x = evt->data.touch.x; + int y = evt->data.touch.y; + if (kDown_ANPTouchAction == evt->data.touch.action) { + + ANPRectF* rect = validTouch(x,y); + if(rect == &m_drawingSurface) { + m_isTouchActive = true; + m_prevX = x; + m_prevY = y; + paint(x, y, true); + return 1; + } + + } else if (kMove_ANPTouchAction == evt->data.touch.action && m_isTouchActive) { + paint(x, y, true); + return 1; + } else if (kUp_ANPTouchAction == evt->data.touch.action && m_isTouchActive) { + paint(x, y, true); + m_isTouchActive = false; + return 1; + } else if (kCancel_ANPTouchAction == evt->data.touch.action) { + m_isTouchActive = false; + return 1; + } + break; + } + case kMouse_ANPEventType: { + if (kDown_ANPMouseAction == evt->data.mouse.action) { + ANPRectF* rect = validTouch(evt->data.mouse.x, evt->data.mouse.y); + if (rect == &m_drawingSurface) + paint(evt->data.mouse.x, evt->data.mouse.y, false); + else if (rect == &m_inputToggle) + toggleInputMethod(); + else if (rect == &m_colorToggle) + togglePaintColor(); + else if (rect == &m_clearSurface) + drawCleanPlugin(); + } + return 1; + } + default: + break; + } + return 0; // unknown or unhandled event +} + +ANPRectF* PaintPlugin::validTouch(int x, int y) { + + //convert to float + float fx = (int) x; + float fy = (int) y; + + if (fx > m_drawingSurface.left && fx < m_drawingSurface.right && fy > m_drawingSurface.top && fy < m_drawingSurface.bottom) + return &m_drawingSurface; + else if (fx > m_inputToggle.left && fx < m_inputToggle.right && fy > m_inputToggle.top && fy < m_inputToggle.bottom) + return &m_inputToggle; + else if (fx > m_colorToggle.left && fx < m_colorToggle.right && fy > m_colorToggle.top && fy < m_colorToggle.bottom) + return &m_colorToggle; + else if (fx > m_clearSurface.left && fx < m_clearSurface.right && fy > m_clearSurface.top && fy < m_clearSurface.bottom) + return &m_clearSurface; + else + return NULL; +} + +void PaintPlugin::toggleInputMethod() { + m_isTouchCurrentInput = !m_isTouchCurrentInput; + + // lock only the input toggle and redraw the canvas + ANPCanvas* lockedCanvas = getCanvas(&m_colorToggle); + drawCleanPlugin(lockedCanvas); +} + +void PaintPlugin::togglePaintColor() { + if (m_activePaint == m_paintBlue) + m_activePaint = m_paintRed; + else if (m_activePaint == m_paintGreen) + m_activePaint = m_paintBlue; + else + m_activePaint = m_paintGreen; + + // lock only the color toggle and redraw the canvas + ANPCanvas* lockedCanvas = getCanvas(&m_colorToggle); + drawCleanPlugin(lockedCanvas); +} + +void PaintPlugin::paint(int x, int y, bool isTouch) { + NPP instance = this->inst(); + + // check to make sure the input types match + if (m_isTouchCurrentInput != isTouch) + return; + + //TODO do not paint outside the drawing surface (mouse & touch) + + // handle the simple "mouse" paint (draw a point) + if (!isTouch) { + + ANPRectF point; + point.left = (float) x-3; + point.top = (float) y-3; + point.right = (float) x+3; + point.bottom = (float) y+3; + + // get a canvas that is only locked around the point + ANPCanvas* canvas = getCanvas(&point); + gCanvasI.drawOval(canvas, &point, m_activePaint); + releaseCanvas(canvas); + return; + } + + // TODO handle the complex "touch" paint (draw a line) +} |
