Home | History | Annotate | Download | only in src
      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 
     25 class SkiaInstance;
     26 
     27 // Used by SkDebugf
     28 SkiaInstance* gPluginInstance;
     29 
     30 void FlushCallback(void* data, int32_t result);
     31 
     32 static 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.
     45 class SkiaInstance : public pp::Instance {
     46 public:
     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 
    119 private:
    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 
    132 void FlushCallback(void* data, int32_t result) {
    133     static_cast<SkiaInstance*>(data)->OnFlush();
    134 }
    135 
    136 class SkiaModule : public pp::Module {
    137 public:
    138     SkiaModule() : pp::Module() {}
    139     virtual ~SkiaModule() {}
    140 
    141     virtual pp::Instance* CreateInstance(PP_Instance instance) {
    142         return new SkiaInstance(instance);
    143     }
    144 };
    145 
    146 namespace pp {
    147 Module* CreateModule() {
    148     return new SkiaModule();
    149 }
    150 }  // namespace pp
    151