1#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGPipe.h"
5#include "SkSockets.h"
6#include "SkNetPipeController.h"
7#include "SkCornerPathEffect.h"
8#include "SkOSMenu.h"
9#include <map>
10
11/**
12 * Drawing Server
13 *
14 * This simple drawing server can accept connections from multiple drawing
15 * clients simultaneously. It accumulates drawing data from each client each
16 * frame, stores it in the appropriate place, and then broadcasts incremental
17 * changes back to all the clients. Each logical packet, meaning one brush
18 * stoke in this case can be of two types, append and replace. Append types are
19 * completed strokes ready to be stored in the fData queue and will no longer be
20 * modified. Replace types are drawing operations that are still in progress on
21 * the client side, so they are appended to fBuffer. The location and size of
22 * the buffered data for each client is stored in a map and updated properly.
23 * Each time a new replace drawing call is received from a client, its previous
24 * buffered data is discarded.
25 * Since the Server keeps all the complete drawing data and the latest buffered
26 * data, it's able to switch between vector and bitmap drawing
27 */
28
29class DrawingServerView : public SampleView {
30public:
31    DrawingServerView(){
32        fServer = new SkTCPServer(40000);
33        fServer->suspendWrite();
34        fTotalBytesRead = fTotalBytesWritten = 0;
35        fVector = true;
36    }
37    ~DrawingServerView() {
38        delete fServer;
39        fData.reset();
40        fBuffer.reset();
41        fClientMap.clear();
42    }
43
44    virtual void requestMenu(SkOSMenu* menu) {
45        menu->setTitle("Drawing Server");
46        menu->appendAction("Clear", this->getSinkID());
47        menu->appendSwitch("Vector", "Vector", this->getSinkID(), fVector);
48    }
49
50protected:
51    static void readData(int cid, const void* data, size_t size,
52                         SkSocket::DataType type, void* context) {
53        DrawingServerView* view = (DrawingServerView*)context;
54        view->onRead(cid, data, size, type);
55    }
56
57    void onRead(int cid, const void* data, size_t size, SkSocket::DataType type) {
58        if (NULL == data && size <= 0)
59            return;
60
61        ClientState* cs;
62        std::map<int, ClientState*>::iterator it = fClientMap.find(cid);
63        if (it == fClientMap.end()) { //New client
64            cs = new ClientState;
65            cs->bufferBase = 0;
66            cs->bufferSize = 0;
67            fClientMap[cid] = cs;
68        }
69        else {
70            cs = it->second;
71        }
72
73        if (type == SkSocket::kPipeReplace_type) {
74            fBuffer.remove(cs->bufferBase, cs->bufferSize);
75
76            for (it = fClientMap.begin(); it != fClientMap.end(); ++it) {
77                if (cid == it->first)
78                    continue;
79                else {
80                    if (it->second->bufferBase > cs->bufferBase) {
81                        it->second->bufferBase -= cs->bufferSize;
82                        SkASSERT(it->second->bufferBase >= 0);
83                    }
84                }
85            }
86
87            cs->bufferBase = fBuffer.count();
88            cs->bufferSize = size;
89            fBuffer.append(size, (const char*)data);
90        }
91        else if (type == SkSocket::kPipeAppend_type) {
92            fData.append(size, (const char*)data);
93            fServer->resumeWrite();
94            fServer->writePacket(fData.begin() + fTotalBytesWritten,
95                                 fData.count() - fTotalBytesWritten,
96                                 SkSocket::kPipeAppend_type);
97            fTotalBytesWritten = fData.count();
98            fServer->suspendWrite();
99        }
100        else {
101            //other types of data
102        }
103    }
104
105    bool onQuery(SkEvent* evt) {
106        if (SampleCode::TitleQ(*evt)) {
107            SampleCode::TitleR(evt, "Drawing Server");
108            return true;
109        }
110        return this->INHERITED::onQuery(evt);
111    }
112
113    bool onEvent(const SkEvent& evt) {
114        if (SkOSMenu::FindAction(evt, "Clear")) {
115            this->clear();
116            return true;
117        }
118        if (SkOSMenu::FindSwitchState(evt, "Vector", &fVector)) {
119            this->clearBitmap();
120            return true;
121        }
122        return this->INHERITED::onEvent(evt);
123    }
124
125
126    virtual void onDrawContent(SkCanvas* canvas) {
127        if (fCurrMatrix != canvas->getTotalMatrix()) {
128            fTotalBytesRead = 0;
129            fCurrMatrix = canvas->getTotalMatrix();
130        }
131
132        fServer->acceptConnections();
133        if (fServer->readPacket(readData, this) > 0) {
134            fServer->resumeWrite();
135        }
136        else {
137            fServer->suspendWrite();
138        }
139
140        size_t bytesRead;
141        SkGPipeReader::Status stat;
142        SkCanvas bufferCanvas(fBase);
143        SkCanvas* tempCanvas;
144        while (fTotalBytesRead < fData.count()) {
145            if (fVector) {
146                tempCanvas = canvas;
147            } else {
148                tempCanvas = &bufferCanvas;
149            }
150            SkGPipeReader reader(tempCanvas);
151            stat = reader.playback(fData.begin() + fTotalBytesRead,
152                                   fData.count() - fTotalBytesRead,
153                                   &bytesRead);
154            SkASSERT(SkGPipeReader::kError_Status != stat);
155            fTotalBytesRead += bytesRead;
156        }
157        if (fVector) {
158            fTotalBytesRead = 0;
159        } else {
160            canvas->drawBitmap(fBase, 0, 0, NULL);
161        }
162
163        size_t totalBytesRead = 0;
164        while (totalBytesRead < fBuffer.count()) {
165            SkGPipeReader reader(canvas);
166            stat = reader.playback(fBuffer.begin() + totalBytesRead,
167                                   fBuffer.count() - totalBytesRead,
168                                   &bytesRead);
169            SkASSERT(SkGPipeReader::kError_Status != stat);
170            totalBytesRead += bytesRead;
171        }
172
173        fServer->writePacket(fBuffer.begin(), fBuffer.count(),
174                             SkSocket::kPipeReplace_type);
175
176        this->inval(NULL);
177    }
178
179    virtual void onSizeChange() {
180        this->INHERITED::onSizeChange();
181        fBase.setConfig(SkBitmap::kARGB_8888_Config,
182                        this->width(),
183                        this->height());
184        fBase.allocPixels(NULL);
185        this->clearBitmap();
186    }
187
188private:
189    void clear() {
190        fData.reset();
191        fBuffer.reset();
192        fTotalBytesRead = fTotalBytesWritten = 0;
193        fClientMap.clear();
194        this->clearBitmap();
195    }
196    void clearBitmap() {
197        fTotalBytesRead = 0;
198        fBase.eraseColor(fBGColor);
199    }
200
201    struct ClientState {
202        int bufferBase;
203        int bufferSize;
204    };
205
206    std::map<int, ClientState*> fClientMap;
207    SkTDArray<char>             fData;
208    SkTDArray<char>             fBuffer;
209    size_t                      fTotalBytesRead;
210    size_t                      fTotalBytesWritten;
211    SkMatrix                    fCurrMatrix;
212    SkBitmap                    fBase;
213    bool                        fVector;
214    SkTCPServer*                fServer;
215    typedef SampleView INHERITED;
216};
217
218
219///////////////////////////////////////////////////////////////////////////////
220
221static SkView* MyFactory() { return new DrawingServerView; }
222static SkViewRegister reg(MyFactory);
223