adding first pass of a sample paint plugin based on surface views.
diff --git a/samples/BrowserPlugin/jni/Android.mk b/samples/BrowserPlugin/jni/Android.mk
index 329a6fd..c3acbd8 100644
--- a/samples/BrowserPlugin/jni/Android.mk
+++ b/samples/BrowserPlugin/jni/Android.mk
@@ -34,6 +34,7 @@
 	audio/AudioPlugin.cpp \
 	background/BackgroundPlugin.cpp \
 	form/FormPlugin.cpp \
+	paint/PaintPlugin.cpp \
 	surface/SurfacePlugin.cpp \
 
 LOCAL_C_INCLUDES += \
@@ -42,6 +43,7 @@
 	$(LOCAL_PATH)/audio \
 	$(LOCAL_PATH)/background \
 	$(LOCAL_PATH)/form \
+	$(LOCAL_PATH)/paint \
 	$(LOCAL_PATH)/surface \
 	external/webkit/WebCore/bridge \
 	external/webkit/WebCore/plugins \
diff --git a/samples/BrowserPlugin/jni/main.cpp b/samples/BrowserPlugin/jni/main.cpp
index 7e7d042..a0649cd 100644
--- a/samples/BrowserPlugin/jni/main.cpp
+++ b/samples/BrowserPlugin/jni/main.cpp
@@ -32,6 +32,7 @@
 #include "AudioPlugin.h"
 #include "BackgroundPlugin.h"
 #include "FormPlugin.h"
+#include "PaintPlugin.h"
 #include "SurfacePlugin.h"
 #include "android_npapi.h"
 
@@ -155,6 +156,31 @@
     }
     /* END: STANDARD PLUGIN FRAMEWORK */
 
+    // select the drawing model based on user input
+    ANPDrawingModel model = kBitmap_ANPDrawingModel;
+
+    for (int i = 0; i < argc; i++) {
+        if (!strcmp(argn[i], "DrawingModel")) {
+            if (!strcmp(argv[i], "Bitmap")) {
+                model = kBitmap_ANPDrawingModel;
+            }
+            else if (!strcmp(argv[i], "Surface")) {
+               model = kSurface_ANPDrawingModel;
+            }
+            gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model);
+            break;
+        }
+    }
+
+    // notify the plugin API of the drawing model we wish to use. This must be
+    // done prior to creating certain subPlugin objects (e.g. surfaceViews)
+    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")) {
@@ -174,6 +200,10 @@
                 obj->pluginType = kForm_PluginType;
                 obj->activePlugin = new FormPlugin(instance);
             }
+            else if (!strcmp(argv[i], "Paint")) {
+                obj->pluginType = kPaint_PluginType;
+                obj->activePlugin = new PaintPlugin(instance);
+            }
             else if (!strcmp(argv[i], "RGBA_Surface")) {
                 obj->pluginType = kSurface_PluginType;
                 obj->activePlugin = new SurfacePlugin(instance, kRGBA_ANPSurfaceType);
@@ -185,40 +215,17 @@
 
     // if no pluginType is specified then default to Animation
     if (!obj->pluginType) {
+        gLogI.log(instance, kError_ANPLogType, "------ %p No PluginType attribute was found", instance);
         obj->pluginType = kAnimation_PluginType;
         obj->activePlugin = new BallAnimation(instance);
     }
 
-    // select the drawing model based on user input
-    ANPDrawingModel model = kBitmap_ANPDrawingModel;
-
-    for (int i = 0; i < argc; i++) {
-        if (!strcmp(argn[i], "DrawingModel")) {
-            if (!strcmp(argv[i], "Bitmap")) {
-                model = kBitmap_ANPDrawingModel;
-            }
-            else if (!strcmp(argv[i], "Surface")) {
-               model = kSurface_ANPDrawingModel;
-            }
-            gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model);
-            break;
-        }
-    }
-
     // check to ensure the pluginType supports the model
     if (!obj->activePlugin->supportsDrawingModel(model)) {
         gLogI.log(instance, kError_ANPLogType, "------ %p Unsupported DrawingModel (%d)", instance, model);
         return NPERR_GENERIC_ERROR;
     }
 
-    // notify the plugin API of the drawing model we wish to use
-    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;
-    }
-
     return NPERR_NO_ERROR;
 }
 
diff --git a/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp b/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp
new file mode 100644
index 0000000..cad0bae
--- /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)
+}
diff --git a/samples/BrowserPlugin/jni/paint/PaintPlugin.h b/samples/BrowserPlugin/jni/paint/PaintPlugin.h
new file mode 100644
index 0000000..6671a30
--- /dev/null
+++ b/samples/BrowserPlugin/jni/paint/PaintPlugin.h
@@ -0,0 +1,71 @@
+/*
+ * 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 "PluginObject.h"
+#include <stdio.h>
+
+#ifndef paintPlugin__DEFINED
+#define paintPlugin__DEFINED
+
+class PaintPlugin : public SubPlugin {
+public:
+    PaintPlugin(NPP inst);
+    virtual ~PaintPlugin();
+    virtual bool supportsDrawingModel(ANPDrawingModel);
+    virtual int16 handleEvent(const ANPEvent* evt);
+private:
+    void        drawCleanPlugin(ANPCanvas* canvas = NULL);
+    ANPCanvas*  getCanvas(ANPRectI* dirtyRect = NULL);
+    ANPCanvas*  getCanvas(ANPRectF* dirtyRect);
+    const char* getColorText();
+    void        paint(int x, int y, bool isTouch);
+    void        releaseCanvas(ANPCanvas*);
+    void        toggleInputMethod();
+    void        togglePaintColor();
+    ANPRectF*   validTouch(int x, int y);
+
+    bool        m_surfaceReady;
+    ANPSurface* m_surface;
+
+    ANPRectF    m_drawingSurface;
+    ANPRectF    m_inputToggle;
+    ANPRectF    m_colorToggle;
+    ANPRectF    m_clearSurface;
+
+    ANPPaint*   m_paintSurface;
+    ANPPaint*   m_paintButton;
+    ANPPaint*   m_paintBlue;
+    ANPPaint*   m_paintGreen;
+    ANPPaint*   m_paintRed;
+
+    ANPPaint*   m_activePaint;
+
+    bool        m_isTouchCurrentInput;
+    bool        m_isTouchActive;
+    int         m_prevX;
+    int         m_prevY;
+};
+
+#endif // paintPlugin__DEFINED