blob: fa059fa70ac33c92d722f447fef37c7502c1f6f4 [file] [log] [blame]
yangsu@google.comf3493f02011-08-08 15:12:05 +00001#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>
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000010
11/**
12 * Drawing Server
13 *
rmistry@google.comd6176b02012-08-23 18:14:13 +000014 * This simple drawing server can accept connections from multiple drawing
15 * clients simultaneously. It accumulates drawing data from each client each
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000016 * 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
rmistry@google.comd6176b02012-08-23 18:14:13 +000020 * 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
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000022 * 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
yangsu@google.comf3493f02011-08-08 15:12:05 +000029class DrawingServerView : public SampleView {
30public:
rmistry@google.comd6176b02012-08-23 18:14:13 +000031 DrawingServerView(){
yangsu@google.comf3493f02011-08-08 15:12:05 +000032 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000043
yangsu@google.comf3493f02011-08-08 15:12:05 +000044 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000049
yangsu@google.comf3493f02011-08-08 15:12:05 +000050protected:
rmistry@google.comd6176b02012-08-23 18:14:13 +000051 static void readData(int cid, const void* data, size_t size,
yangsu@google.comf3493f02011-08-08 15:12:05 +000052 SkSocket::DataType type, void* context) {
53 DrawingServerView* view = (DrawingServerView*)context;
54 view->onRead(cid, data, size, type);
55 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000056
yangsu@google.comf3493f02011-08-08 15:12:05 +000057 void onRead(int cid, const void* data, size_t size, SkSocket::DataType type) {
58 if (NULL == data && size <= 0)
59 return;
rmistry@google.comd6176b02012-08-23 18:14:13 +000060
yangsu@google.comf3493f02011-08-08 15:12:05 +000061 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000072
yangsu@google.comf3493f02011-08-08 15:12:05 +000073 if (type == SkSocket::kPipeReplace_type) {
74 fBuffer.remove(cs->bufferBase, cs->bufferSize);
rmistry@google.comd6176b02012-08-23 18:14:13 +000075
yangsu@google.comf3493f02011-08-08 15:12:05 +000076 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000086
yangsu@google.comf3493f02011-08-08 15:12:05 +000087 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();
yangsu@google.comf3493f02011-08-08 15:12:05 +000099 }
100 else {
101 //other types of data
102 }
103 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000104
yangsu@google.comf3493f02011-08-08 15:12:05 +0000105 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000112
yangsu@google.comf3493f02011-08-08 15:12:05 +0000113 bool onEvent(const SkEvent& evt) {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000114 if (SkOSMenu::FindAction(evt, "Clear")) {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000115 this->clear();
116 return true;
117 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000118 if (SkOSMenu::FindSwitchState(evt, "Vector", &fVector)) {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000119 this->clearBitmap();
120 return true;
121 }
122 return this->INHERITED::onEvent(evt);
123 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000124
125
yangsu@google.comf3493f02011-08-08 15:12:05 +0000126 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000139
yangsu@google.comf3493f02011-08-08 15:12:05 +0000140 size_t bytesRead;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000141 SkGPipeReader::Status stat;
yangsu@google.comf3493f02011-08-08 15:12:05 +0000142 SkCanvas bufferCanvas(fBase);
143 SkCanvas* tempCanvas;
144 while (fTotalBytesRead < fData.count()) {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000145 if (fVector) {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000146 tempCanvas = canvas;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000147 } else {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000148 tempCanvas = &bufferCanvas;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000149 }
yangsu@google.comf3493f02011-08-08 15:12:05 +0000150 SkGPipeReader reader(tempCanvas);
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000151 stat = reader.playback(fData.begin() + fTotalBytesRead,
152 fData.count() - fTotalBytesRead,
153 &bytesRead);
yangsu@google.comf3493f02011-08-08 15:12:05 +0000154 SkASSERT(SkGPipeReader::kError_Status != stat);
155 fTotalBytesRead += bytesRead;
yangsu@google.comf3493f02011-08-08 15:12:05 +0000156 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000157 if (fVector) {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000158 fTotalBytesRead = 0;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000159 } else {
yangsu@google.comf3493f02011-08-08 15:12:05 +0000160 canvas->drawBitmap(fBase, 0, 0, NULL);
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000161 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162
yangsu@google.comf3493f02011-08-08 15:12:05 +0000163 size_t totalBytesRead = 0;
164 while (totalBytesRead < fBuffer.count()) {
165 SkGPipeReader reader(canvas);
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000166 stat = reader.playback(fBuffer.begin() + totalBytesRead,
167 fBuffer.count() - totalBytesRead,
168 &bytesRead);
169 SkASSERT(SkGPipeReader::kError_Status != stat);
yangsu@google.comf3493f02011-08-08 15:12:05 +0000170 totalBytesRead += bytesRead;
171 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000172
173 fServer->writePacket(fBuffer.begin(), fBuffer.count(),
yangsu@google.comf3493f02011-08-08 15:12:05 +0000174 SkSocket::kPipeReplace_type);
175
176 this->inval(NULL);
177 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000178
yangsu@google.comf3493f02011-08-08 15:12:05 +0000179 virtual void onSizeChange() {
180 this->INHERITED::onSizeChange();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181 fBase.setConfig(SkBitmap::kARGB_8888_Config,
182 this->width(),
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000183 this->height());
yangsu@google.comf3493f02011-08-08 15:12:05 +0000184 fBase.allocPixels(NULL);
185 this->clearBitmap();
186 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000187
yangsu@google.comf3493f02011-08-08 15:12:05 +0000188private:
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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000200
yangsu@google.comf3493f02011-08-08 15:12:05 +0000201 struct ClientState {
202 int bufferBase;
203 int bufferSize;
204 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000205
yangsu@google.comf3493f02011-08-08 15:12:05 +0000206 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);