iOS/Cocoa SampleApp, Drawingboard, and Networking updates
http://codereview.appspot.com/4843041/
http://codereview.appspot.com/4826061/
http://codereview.appspot.com/4832044/
http://codereview.appspot.com/4798055/


git-svn-id: http://skia.googlecode.com/svn/trunk@2058 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/DrawingBoard/SampleDrawingClient.cpp b/experimental/DrawingBoard/SampleDrawingClient.cpp
new file mode 100644
index 0000000..9885d51
--- /dev/null
+++ b/experimental/DrawingBoard/SampleDrawingClient.cpp
@@ -0,0 +1,250 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGPipe.h"
+#include "SkSockets.h"
+#include "SkNetPipeController.h"
+#include "SkCornerPathEffect.h"
+#include "SkColorPalette.h"
+#include "SkOSMenu.h"
+
+#define MAX_READ_PER_FRAME 5
+class DrawingClientView : public SampleView {
+public:
+	DrawingClientView() {
+        fSocket = NULL;
+        fTotalBytesRead = 0;
+        fPalette = new SkColorPalette;
+        fPalette->setSize(100, 300);
+        fPalette->setVisibleP(true);
+        this->attachChildToFront(fPalette);
+        fPalette->unref();
+        fBrushSize = SkFloatToScalar(2.5);
+        fAA = false;
+        fPaletteVisible = true;
+        fSync = false;
+        fVector = false;
+    }
+    ~DrawingClientView() {
+        if (fSocket) {
+            delete fSocket;
+        }
+        fData.reset();
+        fBuffer.reset();
+    }
+    
+    virtual void requestMenu(SkOSMenu* menu) {
+        menu->setTitle("Drawing Client");
+        menu->appendTextField("Server IP", "Server IP", this->getSinkID(), "IP address or hostname");
+        menu->appendSwitch("Vector", "Vector", this->getSinkID(), fVector);
+        menu->appendSlider("Brush Size", "Brush Size", this->getSinkID(), 1.0, 100.0, fBrushSize);
+        menu->appendSwitch("Anti-Aliasing", "AA", this->getSinkID(), fAA);
+        menu->appendSwitch("Show Color Palette", "Palette", this->getSinkID(), fPaletteVisible);
+        menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync);
+        menu->appendAction("Clear", this->getSinkID());
+    }
+    
+protected:
+    
+    static void readData(int cid, const void* data, size_t size,
+                         SkSocket::DataType type, void* context) {
+        DrawingClientView* view = (DrawingClientView*)context;
+        view->onRead(cid, data, size, type);
+    }
+    
+    void onRead(int cid, const void* data, size_t size, SkSocket::DataType type) {
+        if (size > 0) {
+            fBuffer.reset();
+            if (type == SkSocket::kPipeReplace_type)
+                fBuffer.append(size, (const char*)data);
+            else if (type == SkSocket::kPipeAppend_type)
+                fData.append(size, (const char*)data);
+            else {
+                //other types of data
+            }
+        }
+    }
+    
+    bool onQuery(SkEvent* evt) {
+        if (SampleCode::TitleQ(*evt)) {
+            SampleCode::TitleR(evt, "Drawing Client");
+            return true;
+        }
+        
+        return this->INHERITED::onQuery(evt);
+    }
+    
+    bool onEvent(const SkEvent& evt) {;
+        if (SkOSMenu::FindSliderValue(&evt, "Brush Size", &fBrushSize))
+            return true;
+        
+        SkString s;
+        if (SkOSMenu::FindText(&evt, "Server IP", &s)) {
+            if (NULL != fSocket) {
+                delete fSocket;
+            }
+            fSocket = new SkTCPClient(s.c_str(), 40000);
+            fSocket->connectToServer();
+            fSocket->suspendWrite();
+            SkDebugf("Connecting to %s\n", s.c_str());
+            fData.reset();
+            fBuffer.reset();
+            this->inval(NULL);
+            return true;
+        }
+        if (SkOSMenu::FindSwitchState(&evt, "AA", &fAA) ||
+            SkOSMenu::FindSwitchState(&evt, "Sync", &fSync))
+            return true;
+        if (SkOSMenu::FindSwitchState(&evt, "Vector", &fVector)) {
+            this->clearBitmap();
+            return true;
+        }
+        if (SkOSMenu::FindAction(&evt, "Clear")) {
+            this->clear();
+            return true;
+        }
+        if (SkOSMenu::FindSwitchState(&evt, "Palette", &fPaletteVisible)) {
+            fPalette->setVisibleP(fPaletteVisible);
+            return true;
+        }
+        return this->INHERITED::onEvent(evt);
+    }
+    
+    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+        return new Click(this);
+    }
+    
+    virtual bool onClick(SkView::Click* click) {
+        switch (click->fState) {
+            case SkView::Click::kDown_State:
+                fCurrLine.moveTo(click->fCurr);
+                fType = SkSocket::kPipeReplace_type;
+                if (fSocket)
+                    fSocket->resumeWrite();
+                break;
+            case SkView::Click::kMoved_State:
+                fCurrLine.lineTo(click->fCurr);
+                break;
+            case SkView::Click::kUp_State:
+                fType = SkSocket::kPipeAppend_type;
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+    
+    virtual void onDrawContent(SkCanvas* canvas) {
+        if (fSocket) {
+            if (fSocket->isConnected()) {
+                if (fSync) {
+                    int count = 0;
+                    while (fSocket->readPacket(readData, this) > 0 &&
+                           count < MAX_READ_PER_FRAME) 
+                        ++count;
+                }
+                else 
+                    fSocket->readPacket(readData, this);
+            }
+            else 
+                fSocket->connectToServer();
+        }
+        size_t bytesRead = 0;
+        SkCanvas bufferCanvas(fBase);
+        SkCanvas* tempCanvas;
+        while (fTotalBytesRead < fData.count()) {
+            if (fVector)
+                tempCanvas = canvas;
+            else
+                tempCanvas = &bufferCanvas;
+            SkGPipeReader reader(tempCanvas);
+            SkGPipeReader::Status status = reader.playback(fData.begin() + fTotalBytesRead,
+                                                           fData.count() - fTotalBytesRead,
+                                                           &bytesRead);
+            SkASSERT(SkGPipeReader::kError_Status != status);
+            fTotalBytesRead += bytesRead;
+        }
+        if (fVector)
+            fTotalBytesRead = 0;
+        else
+            canvas->drawBitmap(fBase, 0, 0, NULL);
+        
+        size_t totalBytesRead = 0;
+        while (totalBytesRead < fBuffer.count()) {
+            SkGPipeReader reader(canvas);
+            reader.playback(fBuffer.begin() + totalBytesRead, 
+                            fBuffer.count() - totalBytesRead, 
+                            &bytesRead);
+            
+            totalBytesRead += bytesRead;
+        }
+        
+        SkNetPipeController controller(canvas);
+        SkGPipeWriter writer;
+        SkCanvas* writerCanvas = writer.startRecording(&controller, 
+                                                       SkGPipeWriter::kCrossProcess_Flag);
+        
+        //controller.disablePlayback();
+        SkPaint p;
+        p.setColor(fPalette->getColor());
+        p.setStyle(SkPaint::kStroke_Style);
+        p.setStrokeWidth(fBrushSize);
+        p.setStrokeCap(SkPaint::kRound_Cap);
+        p.setStrokeJoin(SkPaint::kRound_Join);
+        p.setAntiAlias(fAA);
+        p.setPathEffect(new SkCornerPathEffect(55))->unref();
+        writerCanvas->drawPath(fCurrLine, p);
+        writer.endRecording();
+        
+        controller.writeToSocket(fSocket, fType);
+        if (fType == SkSocket::kPipeAppend_type && fSocket) {
+            fSocket->suspendWrite();
+            fCurrLine.reset();
+        }
+        
+        this->inval(NULL);
+    }
+    
+    virtual void onSizeChange() {
+        this->INHERITED::onSizeChange();
+        fPalette->setLoc(this->width()-100, 0);
+        fBase.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
+        fBase.allocPixels(NULL);
+        this->clearBitmap();
+    }
+    
+private:
+    void clear() {
+        fData.reset();
+        fBuffer.reset();
+        fCurrLine.reset();
+        fTotalBytesRead = 0;
+        this->clearBitmap();
+    }
+    void clearBitmap() {
+        fTotalBytesRead = 0;
+        fBase.eraseColor(fBGColor);
+    }
+    SkTDArray<char>     fData;
+    SkTDArray<char>     fBuffer;
+    SkBitmap            fBase;
+    SkPath              fCurrLine;
+    SkTCPClient*        fSocket;
+    SkSocket::DataType  fType;
+    SkColorPalette*     fPalette;
+    bool                fPaletteVisible;
+    size_t              fTotalBytesRead;
+    SkScalar            fBrushSize;
+    bool                fAA;
+    bool                fSync;
+    bool                fVector;
+    
+    typedef SampleView INHERITED;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new DrawingClientView; }
+static SkViewRegister reg(MyFactory);
+