Chromium Code Reviews| 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 |