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: 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 50 protected: 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 188 private: 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 221 static SkView* MyFactory() { return new DrawingServerView; } 222 static SkViewRegister reg(MyFactory); 223