OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrCaps.h" | 8 #include "GrCaps.h" |
9 #include "GrContextFactory.h" | 9 #include "GrContextFactory.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 } | 122 } |
123 } | 123 } |
124 png_set_filter(png, 0, PNG_NO_FILTERS); | 124 png_set_filter(png, 0, PNG_NO_FILTERS); |
125 png_set_rows(png, info_ptr, &rows[0]); | 125 png_set_rows(png, info_ptr, &rows[0]); |
126 png_set_write_fn(png, &out, write_png_callback, NULL); | 126 png_set_write_fn(png, &out, write_png_callback, NULL); |
127 png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); | 127 png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); |
128 png_destroy_write_struct(&png, NULL); | 128 png_destroy_write_struct(&png, NULL); |
129 sk_free(rows); | 129 sk_free(rows); |
130 } | 130 } |
131 | 131 |
| 132 SkBitmap* getBitmapFromCanvas(SkCanvas* canvas) { |
| 133 SkBitmap* bmp = new SkBitmap(); |
| 134 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kRGBA_8888_S
kColorType, |
| 135 kOpaque_SkAlphaType); |
| 136 bmp->setInfo(info); |
| 137 if (!canvas->readPixels(bmp, 0, 0)) { |
| 138 fprintf(stderr, "Can't read pixels\n"); |
| 139 return nullptr; |
| 140 } |
| 141 return bmp; |
| 142 } |
| 143 |
132 SkData* writeCanvasToPng(SkCanvas* canvas) { | 144 SkData* writeCanvasToPng(SkCanvas* canvas) { |
133 // capture pixels | 145 // capture pixels |
134 SkBitmap bmp; | 146 SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas)); |
135 bmp.setInfo(canvas->imageInfo()); | 147 SkASSERT(bmp); |
136 if (!canvas->readPixels(&bmp, 0, 0)) { | |
137 fprintf(stderr, "Can't read pixels\n"); | |
138 return nullptr; | |
139 } | |
140 | 148 |
141 // write to png | 149 // write to png |
142 SkDynamicMemoryWStream buffer; | 150 SkDynamicMemoryWStream buffer; |
143 write_png((const png_bytep) bmp.getPixels(), bmp.width(), bmp.height(), buff
er); | 151 write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), b
uffer); |
144 return buffer.copyToData(); | 152 return buffer.copyToData(); |
145 } | 153 } |
146 | 154 |
147 SkCanvas* getCanvasFromRequest(Request* request) { | 155 SkCanvas* getCanvasFromRequest(Request* request) { |
148 GrContextFactory* factory = request->fContextFactory; | 156 GrContextFactory* factory = request->fContextFactory; |
149 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex
tType, | 157 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex
tType, |
150 GrContextFactory::kNone_GLContextO
ptions).fGLContext; | 158 GrContextFactory::kNone_GLContextO
ptions).fGLContext; |
151 gl->makeCurrent(); | 159 gl->makeCurrent(); |
152 SkASSERT(request->fDebugCanvas); | 160 SkASSERT(request->fDebugCanvas); |
153 SkCanvas* target = request->fSurface->getCanvas(); | 161 SkCanvas* target = request->fSurface->getCanvas(); |
154 return target; | 162 return target; |
155 } | 163 } |
156 | 164 |
157 SkData* setupAndDrawToCanvasReturnPng(Request* request, int n) { | 165 void drawToCanvas(Request* request, int n) { |
158 SkCanvas* target = getCanvasFromRequest(request); | 166 SkCanvas* target = getCanvasFromRequest(request); |
159 request->fDebugCanvas->drawTo(target, n); | 167 request->fDebugCanvas->drawTo(target, n); |
160 return writeCanvasToPng(target); | 168 } |
| 169 |
| 170 SkData* drawToPng(Request* request, int n) { |
| 171 drawToCanvas(request, n); |
| 172 return writeCanvasToPng(getCanvasFromRequest(request)); |
161 } | 173 } |
162 | 174 |
163 SkSurface* setupCpuSurface() { | 175 SkSurface* setupCpuSurface() { |
164 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColor
Type, | 176 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColor
Type, |
165 kPremul_SkAlphaType); | 177 kPremul_SkAlphaType); |
166 return SkSurface::NewRaster(info); | 178 return SkSurface::NewRaster(info); |
167 } | 179 } |
168 | 180 |
169 static const size_t kBufferSize = 1024; | 181 static const size_t kBufferSize = 1024; |
170 | 182 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 } | 330 } |
319 | 331 |
320 int n; | 332 int n; |
321 // /img or /img/N | 333 // /img or /img/N |
322 if (commands.count() == 1) { | 334 if (commands.count() == 1) { |
323 n = request->fDebugCanvas->getSize() - 1; | 335 n = request->fDebugCanvas->getSize() - 1; |
324 } else { | 336 } else { |
325 sscanf(commands[1].c_str(), "%d", &n); | 337 sscanf(commands[1].c_str(), "%d", &n); |
326 } | 338 } |
327 | 339 |
328 SkAutoTUnref<SkData> data(setupAndDrawToCanvasReturnPng(request, n)); | 340 SkAutoTUnref<SkData> data(drawToPng(request, n)); |
329 return SendData(connection, data, "image/png"); | 341 return SendData(connection, data, "image/png"); |
330 } | 342 } |
331 }; | 343 }; |
332 | 344 |
| 345 class BreakHandler : public UrlHandler { |
| 346 public: |
| 347 bool canHandle(const char* method, const char* url) override { |
| 348 static const char* kBasePath = "/break"; |
| 349 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 350 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
| 351 } |
| 352 |
| 353 static SkColor GetPixel(Request* request, int x, int y) { |
| 354 SkCanvas* canvas = getCanvasFromRequest(request); |
| 355 canvas->flush(); |
| 356 SkAutoTDelete<SkBitmap> bitmap(getBitmapFromCanvas(canvas)); |
| 357 SkASSERT(bitmap); |
| 358 bitmap->lockPixels(); |
| 359 uint8_t* start = ((uint8_t*) bitmap->getPixels()) + (y * kImageWidth + x
) * 4; |
| 360 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]); |
| 361 bitmap->unlockPixels(); |
| 362 return result; |
| 363 } |
| 364 |
| 365 int handle(Request* request, MHD_Connection* connection, |
| 366 const char* url, const char* method, |
| 367 const char* upload_data, size_t* upload_data_size) override { |
| 368 SkTArray<SkString> commands; |
| 369 SkStrSplit(url, "/", &commands); |
| 370 |
| 371 if (!request->fPicture.get() || commands.count() != 4) { |
| 372 return MHD_NO; |
| 373 } |
| 374 |
| 375 // /break/<n>/<x>/<y> |
| 376 int n; |
| 377 sscanf(commands[1].c_str(), "%d", &n); |
| 378 int x; |
| 379 sscanf(commands[2].c_str(), "%d", &x); |
| 380 int y; |
| 381 sscanf(commands[3].c_str(), "%d", &y); |
| 382 |
| 383 int count = request->fDebugCanvas->getSize(); |
| 384 SkASSERT(n < count); |
| 385 |
| 386 SkCanvas* canvas = getCanvasFromRequest(request); |
| 387 canvas->clear(SK_ColorWHITE); |
| 388 int saveCount = canvas->save(); |
| 389 for (int i = 0; i <= n; ++i) { |
| 390 request->fDebugCanvas->getDrawCommandAt(i)->execute(canvas); |
| 391 } |
| 392 SkColor target = GetPixel(request, x, y); |
| 393 Json::Value response(Json::objectValue); |
| 394 Json::Value startColor(Json::arrayValue); |
| 395 startColor.append(Json::Value(SkColorGetR(target))); |
| 396 startColor.append(Json::Value(SkColorGetG(target))); |
| 397 startColor.append(Json::Value(SkColorGetB(target))); |
| 398 startColor.append(Json::Value(SkColorGetA(target))); |
| 399 response["startColor"] = startColor; |
| 400 response["endColor"] = startColor; |
| 401 response["endOp"] = Json::Value(n); |
| 402 for (int i = n + 1; i < n + count; ++i) { |
| 403 int index = i % count; |
| 404 if (index == 0) { |
| 405 // reset canvas for wraparound |
| 406 canvas->restoreToCount(saveCount); |
| 407 canvas->clear(SK_ColorWHITE); |
| 408 saveCount = canvas->save(); |
| 409 } |
| 410 request->fDebugCanvas->getDrawCommandAt(index)->execute(canvas); |
| 411 SkColor current = GetPixel(request, x, y); |
| 412 if (current != target) { |
| 413 Json::Value endColor(Json::arrayValue); |
| 414 endColor.append(Json::Value(SkColorGetR(current))); |
| 415 endColor.append(Json::Value(SkColorGetG(current))); |
| 416 endColor.append(Json::Value(SkColorGetB(current))); |
| 417 endColor.append(Json::Value(SkColorGetA(current))); |
| 418 response["endColor"] = endColor; |
| 419 response["endOp"] = Json::Value(index); |
| 420 break; |
| 421 } |
| 422 } |
| 423 canvas->restoreToCount(saveCount); |
| 424 SkDynamicMemoryWStream stream; |
| 425 stream.writeText(Json::FastWriter().write(response).c_str()); |
| 426 SkAutoTUnref<SkData> data(stream.copyToData()); |
| 427 return SendData(connection, data, "application/json"); |
| 428 } |
| 429 }; |
| 430 |
333 /** | 431 /** |
334 Updates the clip visualization alpha. On all subsequent /img requests, the cl
ip will be drawn in | 432 Updates the clip visualization alpha. On all subsequent /img requests, the cl
ip will be drawn in |
335 black with the specified alpha. 0 = no visible clip, 255 = fully opaque clip. | 433 black with the specified alpha. 0 = no visible clip, 255 = fully opaque clip. |
336 */ | 434 */ |
337 class ClipAlphaHandler : public UrlHandler { | 435 class ClipAlphaHandler : public UrlHandler { |
338 public: | 436 public: |
339 bool canHandle(const char* method, const char* url) override { | 437 bool canHandle(const char* method, const char* url) override { |
340 static const char* kBasePath = "/clipAlpha/"; | 438 static const char* kBasePath = "/clipAlpha/"; |
341 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && | 439 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
342 0 == strncmp(url, kBasePath, strlen(kBasePath)); | 440 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 // Register handlers | 674 // Register handlers |
577 fHandlers.push_back(new RootHandler); | 675 fHandlers.push_back(new RootHandler); |
578 fHandlers.push_back(new PostHandler); | 676 fHandlers.push_back(new PostHandler); |
579 fHandlers.push_back(new ImgHandler); | 677 fHandlers.push_back(new ImgHandler); |
580 fHandlers.push_back(new ClipAlphaHandler); | 678 fHandlers.push_back(new ClipAlphaHandler); |
581 fHandlers.push_back(new CmdHandler); | 679 fHandlers.push_back(new CmdHandler); |
582 fHandlers.push_back(new InfoHandler); | 680 fHandlers.push_back(new InfoHandler); |
583 fHandlers.push_back(new DownloadHandler); | 681 fHandlers.push_back(new DownloadHandler); |
584 fHandlers.push_back(new DataHandler); | 682 fHandlers.push_back(new DataHandler); |
585 fHandlers.push_back(new FaviconHandler); | 683 fHandlers.push_back(new FaviconHandler); |
| 684 fHandlers.push_back(new BreakHandler); |
586 } | 685 } |
587 | 686 |
588 ~UrlManager() { | 687 ~UrlManager() { |
589 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } | 688 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } |
590 } | 689 } |
591 | 690 |
592 // This is clearly not efficient for a large number of urls and handlers | 691 // This is clearly not efficient for a large number of urls and handlers |
593 int invoke(Request* request, MHD_Connection* connection, const char* url, co
nst char* method, | 692 int invoke(Request* request, MHD_Connection* connection, const char* url, co
nst char* method, |
594 const char* upload_data, size_t* upload_data_size) const { | 693 const char* upload_data, size_t* upload_data_size) const { |
595 for (int i = 0; i < fHandlers.count(); i++) { | 694 for (int i = 0; i < fHandlers.count(); i++) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 MHD_stop_daemon(daemon); | 736 MHD_stop_daemon(daemon); |
638 return 0; | 737 return 0; |
639 } | 738 } |
640 | 739 |
641 #if !defined SK_BUILD_FOR_IOS | 740 #if !defined SK_BUILD_FOR_IOS |
642 int main(int argc, char** argv) { | 741 int main(int argc, char** argv) { |
643 SkCommandLineFlags::Parse(argc, argv); | 742 SkCommandLineFlags::Parse(argc, argv); |
644 return skiaserve_main(); | 743 return skiaserve_main(); |
645 } | 744 } |
646 #endif | 745 #endif |
OLD | NEW |