summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp')
-rw-r--r--chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp b/chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp
new file mode 100644
index 00000000000..fa059fa70ac
--- /dev/null
+++ b/chromium/third_party/skia/experimental/DrawingBoard/SampleDrawingServer.cpp
@@ -0,0 +1,222 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGPipe.h"
+#include "SkSockets.h"
+#include "SkNetPipeController.h"
+#include "SkCornerPathEffect.h"
+#include "SkOSMenu.h"
+#include <map>
+
+/**
+ * Drawing Server
+ *
+ * This simple drawing server can accept connections from multiple drawing
+ * clients simultaneously. It accumulates drawing data from each client each
+ * frame, stores it in the appropriate place, and then broadcasts incremental
+ * changes back to all the clients. Each logical packet, meaning one brush
+ * stoke in this case can be of two types, append and replace. Append types are
+ * completed strokes ready to be stored in the fData queue and will no longer be
+ * modified. Replace types are drawing operations that are still in progress on
+ * the client side, so they are appended to fBuffer. The location and size of
+ * the buffered data for each client is stored in a map and updated properly.
+ * Each time a new replace drawing call is received from a client, its previous
+ * buffered data is discarded.
+ * Since the Server keeps all the complete drawing data and the latest buffered
+ * data, it's able to switch between vector and bitmap drawing
+ */
+
+class DrawingServerView : public SampleView {
+public:
+ DrawingServerView(){
+ fServer = new SkTCPServer(40000);
+ fServer->suspendWrite();
+ fTotalBytesRead = fTotalBytesWritten = 0;
+ fVector = true;
+ }
+ ~DrawingServerView() {
+ delete fServer;
+ fData.reset();
+ fBuffer.reset();
+ fClientMap.clear();
+ }
+
+ virtual void requestMenu(SkOSMenu* menu) {
+ menu->setTitle("Drawing Server");
+ menu->appendAction("Clear", this->getSinkID());
+ menu->appendSwitch("Vector", "Vector", this->getSinkID(), fVector);
+ }
+
+protected:
+ static void readData(int cid, const void* data, size_t size,
+ SkSocket::DataType type, void* context) {
+ DrawingServerView* view = (DrawingServerView*)context;
+ view->onRead(cid, data, size, type);
+ }
+
+ void onRead(int cid, const void* data, size_t size, SkSocket::DataType type) {
+ if (NULL == data && size <= 0)
+ return;
+
+ ClientState* cs;
+ std::map<int, ClientState*>::iterator it = fClientMap.find(cid);
+ if (it == fClientMap.end()) { //New client
+ cs = new ClientState;
+ cs->bufferBase = 0;
+ cs->bufferSize = 0;
+ fClientMap[cid] = cs;
+ }
+ else {
+ cs = it->second;
+ }
+
+ if (type == SkSocket::kPipeReplace_type) {
+ fBuffer.remove(cs->bufferBase, cs->bufferSize);
+
+ for (it = fClientMap.begin(); it != fClientMap.end(); ++it) {
+ if (cid == it->first)
+ continue;
+ else {
+ if (it->second->bufferBase > cs->bufferBase) {
+ it->second->bufferBase -= cs->bufferSize;
+ SkASSERT(it->second->bufferBase >= 0);
+ }
+ }
+ }
+
+ cs->bufferBase = fBuffer.count();
+ cs->bufferSize = size;
+ fBuffer.append(size, (const char*)data);
+ }
+ else if (type == SkSocket::kPipeAppend_type) {
+ fData.append(size, (const char*)data);
+ fServer->resumeWrite();
+ fServer->writePacket(fData.begin() + fTotalBytesWritten,
+ fData.count() - fTotalBytesWritten,
+ SkSocket::kPipeAppend_type);
+ fTotalBytesWritten = fData.count();
+ fServer->suspendWrite();
+ }
+ else {
+ //other types of data
+ }
+ }
+
+ bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Drawing Server");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ bool onEvent(const SkEvent& evt) {
+ if (SkOSMenu::FindAction(evt, "Clear")) {
+ this->clear();
+ return true;
+ }
+ if (SkOSMenu::FindSwitchState(evt, "Vector", &fVector)) {
+ this->clearBitmap();
+ return true;
+ }
+ return this->INHERITED::onEvent(evt);
+ }
+
+
+ virtual void onDrawContent(SkCanvas* canvas) {
+ if (fCurrMatrix != canvas->getTotalMatrix()) {
+ fTotalBytesRead = 0;
+ fCurrMatrix = canvas->getTotalMatrix();
+ }
+
+ fServer->acceptConnections();
+ if (fServer->readPacket(readData, this) > 0) {
+ fServer->resumeWrite();
+ }
+ else {
+ fServer->suspendWrite();
+ }
+
+ size_t bytesRead;
+ SkGPipeReader::Status stat;
+ SkCanvas bufferCanvas(fBase);
+ SkCanvas* tempCanvas;
+ while (fTotalBytesRead < fData.count()) {
+ if (fVector) {
+ tempCanvas = canvas;
+ } else {
+ tempCanvas = &bufferCanvas;
+ }
+ SkGPipeReader reader(tempCanvas);
+ stat = reader.playback(fData.begin() + fTotalBytesRead,
+ fData.count() - fTotalBytesRead,
+ &bytesRead);
+ SkASSERT(SkGPipeReader::kError_Status != stat);
+ fTotalBytesRead += bytesRead;
+ }
+ if (fVector) {
+ fTotalBytesRead = 0;
+ } else {
+ canvas->drawBitmap(fBase, 0, 0, NULL);
+ }
+
+ size_t totalBytesRead = 0;
+ while (totalBytesRead < fBuffer.count()) {
+ SkGPipeReader reader(canvas);
+ stat = reader.playback(fBuffer.begin() + totalBytesRead,
+ fBuffer.count() - totalBytesRead,
+ &bytesRead);
+ SkASSERT(SkGPipeReader::kError_Status != stat);
+ totalBytesRead += bytesRead;
+ }
+
+ fServer->writePacket(fBuffer.begin(), fBuffer.count(),
+ SkSocket::kPipeReplace_type);
+
+ this->inval(NULL);
+ }
+
+ virtual void onSizeChange() {
+ this->INHERITED::onSizeChange();
+ fBase.setConfig(SkBitmap::kARGB_8888_Config,
+ this->width(),
+ this->height());
+ fBase.allocPixels(NULL);
+ this->clearBitmap();
+ }
+
+private:
+ void clear() {
+ fData.reset();
+ fBuffer.reset();
+ fTotalBytesRead = fTotalBytesWritten = 0;
+ fClientMap.clear();
+ this->clearBitmap();
+ }
+ void clearBitmap() {
+ fTotalBytesRead = 0;
+ fBase.eraseColor(fBGColor);
+ }
+
+ struct ClientState {
+ int bufferBase;
+ int bufferSize;
+ };
+
+ std::map<int, ClientState*> fClientMap;
+ SkTDArray<char> fData;
+ SkTDArray<char> fBuffer;
+ size_t fTotalBytesRead;
+ size_t fTotalBytesWritten;
+ SkMatrix fCurrMatrix;
+ SkBitmap fBase;
+ bool fVector;
+ SkTCPServer* fServer;
+ typedef SampleView INHERITED;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new DrawingServerView; }
+static SkViewRegister reg(MyFactory);