/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/image_data.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/point.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/var.h" #include "SkBitmap.h" #include "SkCanvas.h" #include "SkColor.h" #include "SkGraphics.h" #include "SkStream.h" #include "SkString.h" class SkiaInstance; // Used by SkDebugf SkiaInstance* gPluginInstance; void FlushCallback(void* data, int32_t result); static void doDraw(SkCanvas* canvas, const SkPaint& paint, const char text[]) { canvas->drawColor(SK_ColorWHITE); SkPaint red; red.setColor(SK_ColorRED); canvas->drawCircle(150.0, 150.0, 100.0, red); SkRect bounds; canvas->getClipBounds(&bounds); canvas->drawText(text, strlen(text), bounds.centerX(), bounds.centerY(), paint); } // Skia's subclass of pp::Instance, our interface with the browser. class SkiaInstance : public pp::Instance { public: explicit SkiaInstance(PP_Instance instance) : pp::Instance(instance) , fCanvas(NULL) , fFlushLoopRunning(false) , fFlushPending(false) { gPluginInstance = this; SkGraphics::Init(); } virtual ~SkiaInstance() { SkGraphics::Term(); gPluginInstance = NULL; } virtual void HandleMessage(const pp::Var& var_message) { // Receive a message from javascript. } void Paint() { if (!fImage.is_null()) { SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(30)); paint.setTextAlign(SkPaint::kCenter_Align); doDraw(fCanvas, paint, "Hello"); fDeviceContext.PaintImageData(fImage, pp::Point(0, 0)); if (!fFlushPending) { fFlushPending = true; fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this)); } else { SkDebugf("A flush is pending... Skipping flush.\n"); } } else { SkDebugf("No pixels to write to!\n"); } } virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { if (position.size().width() == fWidth && position.size().height() == fHeight) { return; // We don't care about the position, only the size. } fWidth = position.size().width(); fHeight = position.size().height(); fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); if (!BindGraphics(fDeviceContext)) { SkDebugf("Couldn't bind the device context\n"); return; } fImage = pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, pp::Size(fWidth, fHeight), false); fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fWidth, fHeight); fBitmap.setPixels(fImage.data()); if (fCanvas) { delete fCanvas; } fCanvas = new SkCanvas(fBitmap); fCanvas->clear(SK_ColorWHITE); if (!fFlushLoopRunning) { Paint(); } } void OnFlush() { fFlushLoopRunning = true; fFlushPending = false; Paint(); } private: pp::Graphics2D fDeviceContext; pp::ImageData fImage; int fWidth; int fHeight; SkBitmap fBitmap; SkCanvas* fCanvas; bool fFlushLoopRunning; bool fFlushPending; }; void FlushCallback(void* data, int32_t result) { static_cast(data)->OnFlush(); } class SkiaModule : public pp::Module { public: SkiaModule() : pp::Module() {} virtual ~SkiaModule() {} virtual pp::Instance* CreateInstance(PP_Instance instance) { return new SkiaInstance(instance); } }; namespace pp { Module* CreateModule() { return new SkiaModule(); } } // namespace pp