16a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include <cstdio> 26a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include <string> 36a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 46a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/completion_callback.h" 56a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/graphics_2d.h" 66a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/image_data.h" 76a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/instance.h" 86a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/module.h" 96a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "ppapi/cpp/var.h" 106a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 116a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SampleApp.h" 126a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SkApplication.h" 136a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SkCanvas.h" 146a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SkBitmap.h" 156a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SkEvent.h" 166a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com#include "SkWindow.h" 176a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 186a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comclass SkiaInstance; 196a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 206a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comnamespace { 216a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid FlushCallback(void* data, int32_t result); 226a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 236a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 246a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comSkiaInstance* gPluginInstance; 256a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comextern int main(int, char**); 266a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 276a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comclass SkiaInstance : public pp::Instance { 286a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com public: 296a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com explicit SkiaInstance(PP_Instance instance) : pp::Instance(instance), 306a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fFlushPending(false), 316a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext(NULL), 326a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fPixelBuffer(NULL) 336a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com { 346a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com gPluginInstance = this; 356a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com application_init(); 366a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com char* commandName = "SampleApp"; 376a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fWindow = new SampleWindow(NULL, 0, &commandName, NULL); 386a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 396a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 406a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com virtual ~SkiaInstance() { 416a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com gPluginInstance = NULL; 426a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com delete fWindow; 436a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com application_term(); 446a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 456a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 466a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com virtual void HandleMessage(const pp::Var& var_message) { 476a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Receive a message from javascript. Right now this just signals us to 486a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // get started. 496a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com uint32_t width = 500; 506a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com uint32_t height = 500; 516a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com char buffer[2048]; 526a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com sprintf(buffer, "SetSize:%d,%d", width, height); 536a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com PostMessage(buffer); 546a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 556a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 566a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com virtual void DidChangeView(const pp::Rect& position, 576a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com const pp::Rect& clip) { 586a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (position.size().width() == width() && 596a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com position.size().height() == height()) { 606a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return; // Size didn't change, no need to update anything. 616a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 626a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Create a new device context with the new size. 636a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com DestroyContext(); 646a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com CreateContext(position.size()); 656a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Delete the old pixel buffer and create a new one. 666a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com delete fPixelBuffer; 676a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fPixelBuffer = NULL; 686a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (fGraphics2dContext != NULL) { 696a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fPixelBuffer = new pp::ImageData(this, 706a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com PP_IMAGEDATAFORMAT_BGRA_PREMUL, 716a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext->size(), 726a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com false); 736a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fWindow->resize(position.size().width(), position.size().height()); 746a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fWindow->update(NULL); 756a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com paint(); 766a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 776a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 786a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 796a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Indicate whether a flush is pending. This can only be called from the 806a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // main thread; it is not thread safe. 816a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com bool flush_pending() const { 826a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return fFlushPending; 836a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 846a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com void set_flush_pending(bool flag) { 856a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fFlushPending = flag; 866a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 876a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 886a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com void paint() { 896a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (fPixelBuffer) { 906a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Draw some stuff. TODO(borenet): Actually have SampleApp draw into 916a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // the plugin area. 926a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com uint32_t w = fPixelBuffer->size().width(); 936a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com uint32_t h = fPixelBuffer->size().height(); 946a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com uint32_t* data = (uint32_t*) fPixelBuffer->data(); 956a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Create a bitmap using the fPixelBuffer pixels 966a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkBitmap bitmap; 976a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h); 986a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com bitmap.setPixels(data); 996a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Create a canvas with the bitmap as the backend 1006a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkCanvas canvas(bitmap); 1016a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1026a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com canvas.drawColor(SK_ColorBLUE); 1036a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkRect rect = SkRect::MakeXYWH(10, 10, 80, 80); 1046a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkPaint rect_paint; 1056a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com rect_paint.setStyle(SkPaint::kFill_Style); 1066a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com rect_paint.setColor(SK_ColorRED); 1076a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com canvas.drawRect(rect, rect_paint); 1086a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1096a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com FlushPixelBuffer(); 1106a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1116a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1126a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1136a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comprivate: 1146a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com int width() const { 1156a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return fPixelBuffer ? fPixelBuffer->size().width() : 0; 1166a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1176a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1186a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com int height() const { 1196a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return fPixelBuffer ? fPixelBuffer->size().height() : 0; 1206a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1216a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1226a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com bool IsContextValid() const { 1236a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return fGraphics2dContext != NULL; 1246a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1256a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1266a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com void CreateContext(const pp::Size& size) { 1276a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (IsContextValid()) 1286a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return; 1296a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext = new pp::Graphics2D(this, size, false); 1306a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (!BindGraphics(*fGraphics2dContext)) { 1316a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkDebugf("Couldn't bind the device context"); 1326a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1336a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1346a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1356a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com void DestroyContext() { 1366a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (!IsContextValid()) 1376a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return; 1386a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com delete fGraphics2dContext; 1396a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext = NULL; 1406a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1416a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1426a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com void FlushPixelBuffer() { 1436a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (!IsContextValid()) 1446a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return; 1456a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // Note that the pixel lock is held while the buffer is copied into the 1466a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com // device context and then flushed. 1476a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext->PaintImageData(*fPixelBuffer, pp::Point()); 1486a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com if (flush_pending()) 1496a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return; 1506a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com set_flush_pending(true); 1516a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com fGraphics2dContext->Flush(pp::CompletionCallback(&FlushCallback, this)); 1526a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1536a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1546a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com bool fFlushPending; 1556a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com pp::Graphics2D* fGraphics2dContext; 1566a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com pp::ImageData* fPixelBuffer; 1576a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SampleWindow* fWindow; 1586a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com}; 1596a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1606a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comclass SkiaModule : public pp::Module { 1616a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.compublic: 1626a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com SkiaModule() : pp::Module() {} 1636a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com virtual ~SkiaModule() {} 1646a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1656a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com virtual pp::Instance* CreateInstance(PP_Instance instance) { 1666a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com gPluginInstance = new SkiaInstance(instance); 1676a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return gPluginInstance; 1686a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com } 1696a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com}; 1706a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1716a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comnamespace { 1726a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid FlushCallback(void* data, int32_t result) { 1736a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com static_cast<SkiaInstance*>(data)->set_flush_pending(false); 1746a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 1756a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 1766a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1776a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comnamespace pp { 1786a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comModule* CreateModule() { 1796a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com return new SkiaModule(); 1806a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 1816a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} // namespace pp 1826a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1836a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1846a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com/////////////////////////////////////////// 1856a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com///////////// SkOSWindow impl ///////////// 1866a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com/////////////////////////////////////////// 1876a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1886a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid SkOSWindow::onSetTitle(const char title[]) 1896a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com{ 1906a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com char buffer[2048]; 1916a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com sprintf(buffer, "SetTitle:%s", title); 1926a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com gPluginInstance->PostMessage(buffer); 1936a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 1946a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 1956a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid SkOSWindow::onHandleInval(const SkIRect& rect) 1966a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com{ 1976a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com gPluginInstance->paint(); 1986a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 1996a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 2006a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid SkOSWindow::onPDFSaved(const char title[], const char desc[], 2016a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com const char path[]) { 2026a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 2036a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 2046a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com/////////////////////////////////////////// 2056a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com/////////////// SkEvent impl ////////////// 2066a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com/////////////////////////////////////////// 2076a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 2086a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid SkEvent::SignalQueueTimer(SkMSec ms) { 2096a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 2106a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com 2116a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.comvoid SkEvent::SignalNonEmptyQueue() { 2126a98b8c0b5ffe1a23902cdf7e692f702b703eaebborenet@google.com} 213