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 
29 class DrawingServerView : public SampleView {
30 public:
DrawingServerView()31     DrawingServerView(){
32         fServer = new SkTCPServer(40000);
33         fServer->suspendWrite();
34         fTotalBytesRead = fTotalBytesWritten = 0;
35         fVector = true;
36     }
~DrawingServerView()37     ~DrawingServerView() {
38         delete fServer;
39         fData.reset();
40         fBuffer.reset();
41         fClientMap.clear();
42     }
43 
requestMenu(SkOSMenu * menu)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 
50 protected:
readData(int cid,const void * data,size_t size,SkSocket::DataType type,void * context)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 
onRead(int cid,const void * data,size_t size,SkSocket::DataType type)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 
onQuery(SkEvent * evt)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 
onEvent(const SkEvent & evt)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 
onDrawContent(SkCanvas * canvas)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 
onSizeChange()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 
188 private:
clear()189     void clear() {
190         fData.reset();
191         fBuffer.reset();
192         fTotalBytesRead = fTotalBytesWritten = 0;
193         fClientMap.clear();
194         this->clearBitmap();
195     }
clearBitmap()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 
MyFactory()221 static SkView* MyFactory() { return new DrawingServerView; }
222 static SkViewRegister reg(MyFactory);
223