From 609d97918788c077514f190b0f1087ccbd420f5d Mon Sep 17 00:00:00 2001 From: joshualitt Date: Wed, 27 Jan 2016 11:07:23 -0800 Subject: [PATCH] Wire up JsonCanvas in skiaserve BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1640333002 Review URL: https://codereview.chromium.org/1640333002 --- gyp/skiaserve.gyp | 4 ++ tools/skiaserve/skiaserve.cpp | 146 +++++++++++++++++++++++++----------------- 2 files changed, 91 insertions(+), 59 deletions(-) diff --git a/gyp/skiaserve.gyp b/gyp/skiaserve.gyp index e5d125c..1c5ce5a 100644 --- a/gyp/skiaserve.gyp +++ b/gyp/skiaserve.gyp @@ -15,9 +15,13 @@ 'sources': [ '\n" + "\n" + "\n" + " SkDebugger\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + "\n" + " This is the app." + " \n" + "\n" + "", 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 fPNG; + SkAutoTUnref 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 factory(new GrContextFactory(grContextOpts)); @@ -55,65 +92,32 @@ SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) { gl->makeCurrent(); // draw - SkAutoTUnref 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( - "\n" - "\n" - "\n" - " SkDebugger\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n" - "\n" - " This is the app." - " \n" - "\n" - "", 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 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(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(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 jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHeight, stream)); + jsonCanvas->drawPicture(picture); + jsonCanvas->finish(); + + SkAutoTUnref 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(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); 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 -- 2.7.4