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