1 2/* 3 * Copyright 2013 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "ppapi/cpp/completion_callback.h" 10#include "ppapi/cpp/graphics_2d.h" 11#include "ppapi/cpp/image_data.h" 12#include "ppapi/cpp/instance.h" 13#include "ppapi/cpp/module.h" 14#include "ppapi/cpp/point.h" 15#include "ppapi/cpp/rect.h" 16#include "ppapi/cpp/var.h" 17 18#include "SkBitmap.h" 19#include "SkCanvas.h" 20#include "SkColor.h" 21#include "SkGraphics.h" 22#include "SkStream.h" 23#include "SkString.h" 24 25class SkiaInstance; 26 27// Used by SkDebugf 28SkiaInstance* gPluginInstance; 29 30void FlushCallback(void* data, int32_t result); 31 32static void doDraw(SkCanvas* canvas, const SkPaint& paint, const char text[]) { 33 canvas->drawColor(SK_ColorWHITE); 34 SkPaint red; 35 red.setColor(SK_ColorRED); 36 canvas->drawCircle(150.0, 150.0, 100.0, red); 37 SkRect bounds; 38 canvas->getClipBounds(&bounds); 39 canvas->drawText(text, strlen(text), 40 bounds.centerX(), bounds.centerY(), 41 paint); 42} 43 44// Skia's subclass of pp::Instance, our interface with the browser. 45class SkiaInstance : public pp::Instance { 46public: 47 explicit SkiaInstance(PP_Instance instance) 48 : pp::Instance(instance) 49 , fCanvas(NULL) 50 , fFlushLoopRunning(false) 51 , fFlushPending(false) 52 { 53 gPluginInstance = this; 54 SkGraphics::Init(); 55 } 56 57 virtual ~SkiaInstance() { 58 SkGraphics::Term(); 59 gPluginInstance = NULL; 60 } 61 62 virtual void HandleMessage(const pp::Var& var_message) { 63 // Receive a message from javascript. 64 } 65 66 void Paint() { 67 if (!fImage.is_null()) { 68 SkPaint paint; 69 paint.setAntiAlias(true); 70 paint.setTextSize(SkIntToScalar(30)); 71 paint.setTextAlign(SkPaint::kCenter_Align); 72 doDraw(fCanvas, paint, "Hello"); 73 74 fDeviceContext.PaintImageData(fImage, pp::Point(0, 0)); 75 if (!fFlushPending) { 76 fFlushPending = true; 77 fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this)); 78 } else { 79 SkDebugf("A flush is pending... Skipping flush.\n"); 80 } 81 } else { 82 SkDebugf("No pixels to write to!\n"); 83 } 84 } 85 86 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { 87 if (position.size().width() == fWidth && 88 position.size().height() == fHeight) { 89 return; // We don't care about the position, only the size. 90 } 91 fWidth = position.size().width(); 92 fHeight = position.size().height(); 93 fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); 94 if (!BindGraphics(fDeviceContext)) { 95 SkDebugf("Couldn't bind the device context\n"); 96 return; 97 } 98 fImage = pp::ImageData(this, 99 PP_IMAGEDATAFORMAT_BGRA_PREMUL, 100 pp::Size(fWidth, fHeight), false); 101 fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fWidth, fHeight); 102 fBitmap.setPixels(fImage.data()); 103 if (fCanvas) { 104 delete fCanvas; 105 } 106 fCanvas = new SkCanvas(fBitmap); 107 fCanvas->clear(SK_ColorWHITE); 108 if (!fFlushLoopRunning) { 109 Paint(); 110 } 111 } 112 113 void OnFlush() { 114 fFlushLoopRunning = true; 115 fFlushPending = false; 116 Paint(); 117 } 118 119private: 120 pp::Graphics2D fDeviceContext; 121 pp::ImageData fImage; 122 int fWidth; 123 int fHeight; 124 125 SkBitmap fBitmap; 126 SkCanvas* fCanvas; 127 128 bool fFlushLoopRunning; 129 bool fFlushPending; 130}; 131 132void FlushCallback(void* data, int32_t result) { 133 static_cast<SkiaInstance*>(data)->OnFlush(); 134} 135 136class SkiaModule : public pp::Module { 137public: 138 SkiaModule() : pp::Module() {} 139 virtual ~SkiaModule() {} 140 141 virtual pp::Instance* CreateInstance(PP_Instance instance) { 142 return new SkiaInstance(instance); 143 } 144}; 145 146namespace pp { 147Module* CreateModule() { 148 return new SkiaModule(); 149} 150} // namespace pp 151