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