Index: tools/skiaserve/skiaserve.cpp |
diff --git a/tools/skiaserve/skiaserve.cpp b/tools/skiaserve/skiaserve.cpp |
index aa6d803264c2e06ce26a31fa121d88f4036e1923..fa98d792876f9290a3b5b0b69d85725e45af2e32 100644 |
--- a/tools/skiaserve/skiaserve.cpp |
+++ b/tools/skiaserve/skiaserve.cpp |
@@ -9,6 +9,7 @@ |
#include "GrContextFactory.h" |
#include "SkCanvas.h" |
#include "SkCommandLineFlags.h" |
+#include "SkJSONCanvas.h" |
#include "SkPicture.h" |
#include "SkStream.h" |
#include "SkSurface.h" |
@@ -32,8 +33,44 @@ DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template st |
static const int kImageWidth = 1920; |
static const int kImageHeight = 1080; |
+// TODO move to template file |
+SkString generateTemplate(SkString source) { |
+ SkString debuggerTemplate; |
+ debuggerTemplate.appendf( |
+ "<!DOCTYPE html>\n" |
+ "<html>\n" |
+ "<head>\n" |
+ " <title>SkDebugger</title>\n" |
+ " <meta charset=\"utf-8\" />\n" |
+ " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\n" |
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" |
+ " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n" |
+ " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" |
+ "</head>\n" |
+ "<body class=\"fullbleed layout vertical\">\n" |
+ " <debugger-app-sk>This is the app." |
+ " </debugger-app-sk>\n" |
+ "</body>\n" |
+ "</html>", source.c_str(), source.c_str()); |
+ return debuggerTemplate; |
+ |
+} |
+ |
+struct UploadContext { |
+ SkDynamicMemoryWStream fStream; |
+ MHD_PostProcessor* fPostProcessor; |
+ MHD_Connection* connection; |
+}; |
+ |
+struct Request { |
+ Request() : fUploadContext(nullptr) {} |
+ UploadContext* fUploadContext; |
+ SkAutoTUnref<SkData> fPNG; |
+ SkAutoTUnref<SkPicture> fPicture; |
+}; |
+ |
// TODO factor this out into functions, also handle CPU path |
-SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) { |
+bool setupAndDrawToCanvas(Request* request, SkString* error) { |
GrContextOptions grContextOpts; |
SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)); |
@@ -55,65 +92,32 @@ SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) { |
gl->makeCurrent(); |
// draw |
- SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream)); |
- if (pic.get() == nullptr) { |
+ request->fPicture.reset( |
+ SkPicture::CreateFromStream(request->fUploadContext->fStream.detachAsStream())); |
+ if (!request->fPicture.get()) { |
error->appendf("Could not create picture from stream.\n"); |
- return nullptr; |
+ return false; |
} |
SkCanvas* canvas = surface->getCanvas(); |
- canvas->drawPicture(pic); |
+ canvas->drawPicture(request->fPicture); |
// capture pixels |
SkBitmap bmp; |
bmp.setInfo(canvas->imageInfo()); |
if (!canvas->readPixels(&bmp, 0, 0)) { |
error->appendf("Can't read canvas pixels.\n"); |
- return nullptr; |
+ return false; |
} |
// write to png |
- SkData* data = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100); |
- if (!data) { |
+ request->fPNG.reset(SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100)); |
+ if (!request->fPNG) { |
error->appendf("Can't encode a PNG.\n"); |
- return nullptr; |
+ return false; |
} |
- return data; |
+ return true; |
} |
-// TODO move to template file |
-SkString generateTemplate(SkString source) { |
- SkString debuggerTemplate; |
- debuggerTemplate.appendf( |
- "<!DOCTYPE html>\n" |
- "<html>\n" |
- "<head>\n" |
- " <title>SkDebugger</title>\n" |
- " <meta charset=\"utf-8\" />\n" |
- " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\n" |
- " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" |
- " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n" |
- " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" |
- "</head>\n" |
- "<body class=\"fullbleed layout vertical\">\n" |
- " <debugger-app-sk>This is the app." |
- " </debugger-app-sk>\n" |
- "</body>\n" |
- "</html>", source.c_str(), source.c_str()); |
- return debuggerTemplate; |
- |
-} |
- |
-struct UploadContext { |
- SkDynamicMemoryWStream stream; |
- MHD_PostProcessor* pp; |
- MHD_Connection* connection; |
-}; |
- |
-struct Request { |
- Request() : fUploadContext(nullptr) {} |
- UploadContext* fUploadContext; |
- SkAutoTUnref<SkData> fPNG; |
-}; |
static const size_t kBufferSize = 1024; |
@@ -124,23 +128,34 @@ static int process_upload_data(void* cls, enum MHD_ValueKind kind, |
struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); |
if (0 != size) { |
- uc->stream.write(data, size); |
+ uc->fStream.write(data, size); |
} |
return MHD_YES; |
} |
-static int SendImage(MHD_Connection* connection, const SkData* data) { |
+static int SendData(MHD_Connection* connection, const SkData* data, const char* type) { |
MHD_Response* response = MHD_create_response_from_buffer(data->size(), |
const_cast<void*>(data->data()), |
MHD_RESPMEM_MUST_COPY); |
- MHD_add_response_header(response, "Content-Type", "image/png"); |
+ MHD_add_response_header(response, "Content-Type", type); |
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
MHD_destroy_response(response); |
return ret; |
} |
-static int SendTemplate(MHD_Connection* connection) { |
+static int SendJSON(MHD_Connection* connection, SkPicture* picture) { |
+ SkDynamicMemoryWStream stream; |
+ SkAutoTUnref<SkJSONCanvas> jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHeight, stream)); |
+ jsonCanvas->drawPicture(picture); |
+ jsonCanvas->finish(); |
+ |
+ SkAutoTUnref<SkData> data(stream.copyToData()); |
+ return SendData(connection, data, "application/json"); |
+} |
+ |
+static int SendTemplate(MHD_Connection* connection, bool redirect = false, |
+ const char* redirectUrl = nullptr) { |
SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org")); |
MHD_Response* response = MHD_create_response_from_buffer( |
@@ -148,6 +163,11 @@ static int SendTemplate(MHD_Connection* connection) { |
(void*) const_cast<char*>(debuggerTemplate.c_str()), |
MHD_RESPMEM_MUST_COPY); |
+ if (redirect) { |
+ MHD_add_response_header (response, "Location", redirectUrl); |
+ } |
+ |
+ |
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
jcgregorio
2016/01/27 19:21:19
If it's a redirect the status code needs to be cha
|
MHD_destroy_response(response); |
return ret; |
@@ -170,8 +190,9 @@ int postHandler(Request* request, MHD_Connection* connection, |
// TODO make this a method on request |
uc = new UploadContext; |
uc->connection = connection; |
- uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc); |
- SkASSERT(uc->pp); |
+ uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSize, |
+ &process_upload_data, uc); |
+ SkASSERT(uc->fPostProcessor); |
request->fUploadContext = uc; |
return MHD_YES; |
@@ -179,33 +200,39 @@ int postHandler(Request* request, MHD_Connection* connection, |
// in process upload |
if (0 != *upload_data_size) { |
- SkASSERT(uc->pp); |
- MHD_post_process(uc->pp, upload_data, *upload_data_size); |
+ SkASSERT(uc->fPostProcessor); |
+ MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size); |
*upload_data_size = 0; |
return MHD_YES; |
} |
// end of upload |
- MHD_destroy_post_processor(uc->pp); |
- uc->pp = nullptr; |
+ MHD_destroy_post_processor(uc->fPostProcessor); |
+ uc->fPostProcessor = nullptr; |
// TODO response |
SkString error; |
- SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error); |
- if (!data) { |
+ if (!setupAndDrawToCanvas(request, &error)) { |
// TODO send error |
return MHD_YES; |
} |
- request->fPNG.reset(data); |
- return SendTemplate(connection); |
+ return SendTemplate(connection, true, "/"); |
} |
int imgHandler(Request* request, MHD_Connection* connection, |
const char* upload_data, size_t* upload_data_size) { |
if (request->fPNG.get()) { |
SkData* data = request->fPNG.get(); |
- return SendImage(connection, data); |
+ return SendData(connection, data, "image/png"); |
+ } |
+ return MHD_NO; |
+} |
+ |
+int infoHandler(Request* request, MHD_Connection* connection, |
+ const char* upload_data, size_t* upload_data_size) { |
+ if (request->fPicture.get()) { |
+ return SendJSON(connection, request->fPicture); |
} |
return MHD_NO; |
} |
@@ -217,6 +244,7 @@ public: |
fHandlers.push_back({MHD_HTTP_METHOD_GET, "/", rootHandler}); |
fHandlers.push_back({MHD_HTTP_METHOD_POST, "/new", postHandler}); |
fHandlers.push_back({MHD_HTTP_METHOD_GET, "/img", imgHandler}); |
+ //fHandlers.push_back({MHD_HTTP_METHOD_GET, "/cmd", infoHandler}); |
} |
// This is clearly not efficient for a large number of urls and handlers |