Home | History | Annotate | Download | only in DrawingBoard
      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