| #include "SampleCode.h" | 
 | #include "SkView.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkGradientShader.h" | 
 | #include "SkGPipe.h" | 
 | #include "SkSockets.h" | 
 | #include "SkOSMenu.h" | 
 |  | 
 | /** | 
 |  * A simple networked pipe reader | 
 |  * | 
 |  * This view will connect to a user specified server, in this case meaning any | 
 |  * Skia app that's has a SkTCPServer set up to broadcast its piped drawing data, | 
 |  * received all the data transmitted and attempt to reproduce the drawing calls. | 
 |  * This reader will only keep the latest batch of data. In order to keep up with | 
 |  * the server, which may be producing data at a much higher rate than the reader | 
 |  * is consuming, the reader will attempt multiple reads and only render the | 
 |  * latest frame. this behavior can be adjusted by changing MAX_READS_PER_FRAME | 
 |  * or disabled by setting fSync to false | 
 |  */ | 
 |  | 
 | #define MAX_READS_PER_FRAME 12 | 
 |  | 
 | class NetPipeReaderView : public SampleView { | 
 | public: | 
 |     NetPipeReaderView() { | 
 |         fSocket = NULL; | 
 |         fSync = true; | 
 |     } | 
 |  | 
 |     ~NetPipeReaderView() { | 
 |         if (fSocket) { | 
 |             delete fSocket; | 
 |         } | 
 |         fDataArray.reset(); | 
 |     } | 
 |     virtual void requestMenu(SkOSMenu* menu) { | 
 |         menu->setTitle("Net Pipe Reader"); | 
 |         menu->appendTextField("Server IP", "Server IP", this->getSinkID(), | 
 |                               "IP address"); | 
 |         menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync); | 
 |     } | 
 |  | 
 | protected: | 
 |     static void readData(int cid, const void* data, size_t size, | 
 |                          SkSocket::DataType type, void* context) { | 
 |         NetPipeReaderView* view = (NetPipeReaderView*)context; | 
 |         view->onRead(data, size); | 
 |     } | 
 |  | 
 |     void onRead(const void* data, size_t size) { | 
 |         if (size > 0) | 
 |             fDataArray.append(size, (const char*)data); | 
 |     } | 
 |  | 
 |     bool onQuery(SkEvent* evt) { | 
 |         if (SampleCode::TitleQ(*evt)) { | 
 |             SampleCode::TitleR(evt, "Net Pipe Reader"); | 
 |             return true; | 
 |         } | 
 |         return this->INHERITED::onQuery(evt); | 
 |     } | 
 |  | 
 |     bool onEvent(const SkEvent& evt) { | 
 |         SkString s; | 
 |         if (SkOSMenu::FindText(evt, "Server IP", &s)) { | 
 |             if (NULL != fSocket) { | 
 |                 delete fSocket; | 
 |             } | 
 |             fSocket = new SkTCPClient(s.c_str()); | 
 |             fSocket->connectToServer(); | 
 |             SkDebugf("Connecting to %s\n", s.c_str()); | 
 |             return true; | 
 |         } | 
 |         if (SkOSMenu::FindSwitchState(evt, "Sync", &fSync)) | 
 |             return true; | 
 |         return this->INHERITED::onEvent(evt); | 
 |     } | 
 |  | 
 |     void onDrawContent(SkCanvas* canvas) { | 
 |         if (NULL == fSocket) | 
 |             return; | 
 |  | 
 |         if (fSocket->isConnected()) { | 
 |             int dataToRemove = fDataArray.count(); | 
 |             if (fSync) { | 
 |                 int numreads = 0; | 
 |                 while (fSocket->readPacket(readData, this) > 0 && | 
 |                        numreads < MAX_READS_PER_FRAME) { | 
 |                     // at this point, new data has been read and stored, discard | 
 |                     // old data since it's not needed anymore | 
 |                     SkASSERT(fDataArray.count() > dataToRemove); | 
 |                     fDataArray.remove(0, dataToRemove); | 
 |                     dataToRemove = fDataArray.count(); | 
 |                     ++numreads; | 
 |                 } | 
 |                 // clean up if max reads reached | 
 |                 if (numreads == MAX_READS_PER_FRAME && | 
 |                     fDataArray.count() > dataToRemove) | 
 |                     fDataArray.remove(0, dataToRemove); | 
 |             } | 
 |             else { | 
 |                 if (fSocket->readPacket(readData, this) > 0) | 
 |                     fDataArray.remove(0, dataToRemove); | 
 |             } | 
 |         } | 
 |         else | 
 |             fSocket->connectToServer(); | 
 |  | 
 |         SkGPipeReader reader(canvas); | 
 |         size_t bytesRead; | 
 |         SkGPipeReader::Status fStatus = reader.playback(fDataArray.begin(), | 
 |                                                         fDataArray.count(), | 
 |                                                         &bytesRead); | 
 |         SkASSERT(SkGPipeReader::kError_Status != fStatus); | 
 |         this->inval(NULL); | 
 |     } | 
 |  | 
 | private: | 
 |     bool fSync; | 
 |     SkTDArray<char> fDataArray; | 
 |     SkTCPClient* fSocket; | 
 |     typedef SampleView INHERITED; | 
 | }; | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | static SkView* MyFactory() { return new NetPipeReaderView; } | 
 | static SkViewRegister reg(MyFactory); |