SkHello for NaCl
Not ready to submit.
R=reed@google.com
Review URL: https://codereview.chromium.org/16904003
git-svn-id: http://skia.googlecode.com/svn/trunk@9639 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index 0bb3b70..d8b0205 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,7 @@
pathops_unittest \
pdfviewer \
SampleApp \
+ skhello \
SkiaAndroidApp \
skia_lib \
tests \
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index 2b0550a..d960cdc 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -60,13 +60,23 @@
{
'target_name': 'skhello',
'type': 'executable',
- 'sources': [
- '../tools/skhello.cpp',
- ],
'dependencies': [
'skia_lib.gyp:skia_lib',
- 'pdf.gyp:pdf',
- 'flags.gyp:flags',
+ ],
+ 'conditions': [
+ [ 'skia_os == "nacl"', {
+ 'sources': [
+ '../platform_tools/nacl/src/nacl_hello.cpp',
+ ],
+ }, {
+ 'sources': [
+ '../tools/skhello.cpp',
+ ],
+ 'dependencies': [
+ 'pdf.gyp:pdf',
+ 'flags.gyp:flags',
+ ],
+ }],
],
},
{
diff --git a/platform_tools/nacl/index.html b/platform_tools/nacl/index.html
index abe5d1e..4d87f3e 100644
--- a/platform_tools/nacl/index.html
+++ b/platform_tools/nacl/index.html
@@ -13,6 +13,7 @@
<h1>Skia Native Client Apps</h1>
<p>
<ul>
+ <li><a href="skhello">Skia Hello World</a></li>
<li><a href="tests">Skia Unit Tests</a></li>
<li><a href="debugger">Skia Debugger</a></li>
<li><a href="SampleApp">Skia Sample App</a></li>
diff --git a/platform_tools/nacl/skhello/index.html b/platform_tools/nacl/skhello/index.html
new file mode 100644
index 0000000..4119aed
--- /dev/null
+++ b/platform_tools/nacl/skhello/index.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright 2013 Google Inc.
+
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+<head>
+
+ <title>Skia Hello World</title>
+
+ <script type="text/javascript">
+ "use strict";
+
+ var SkiaModule = null; // Global application object.
+
+ // Force a re-draw of the given element.
+ function refresh(elem) {
+ var old_display_style = elem.style.display;
+ elem.style.display = "none";
+ elem.style.display = old_display_style;
+ }
+
+ // When the module loads, begin running the application.
+ function moduleDidLoad() {
+ SkiaModule = document.getElementById("skia_nacl");
+ run();
+ }
+
+ function handleMessage(message_event) {
+ var skdebugf_cmd = "SkDebugf:";
+ if (message_event.data.indexOf(skdebugf_cmd) == 0) {
+ var msg_contents = message_event.data.slice(skdebugf_cmd.length)
+ console.log("Skia: " + msg_contents);
+ } else {
+ alert(message_event.data);
+ }
+ }
+
+ // Run the application.
+ function run() {
+ if (SkiaModule) {
+ var cmd = "init";
+ SkiaModule.postMessage(cmd);
+ } else {
+ alert("The Skia module has not properly loaded...");
+ }
+ }
+ </script>
+</head>
+<body>
+
+<h1>Skia Hello World</h1>
+<p>
+ <div id="listener">
+ <script type="text/javascript">
+ var listener = document.getElementById('listener');
+ listener.addEventListener('load', moduleDidLoad, true);
+ listener.addEventListener('message', handleMessage, true);
+ </script>
+
+ <embed name="nacl_module"
+ id="skia_nacl"
+ width=300 height=300
+ src="skhello.nmf"
+ type="application/x-nacl" />
+ </div>
+</p>
+</body>
+</html>
diff --git a/platform_tools/nacl/skhello/skhello.nmf b/platform_tools/nacl/skhello/skhello.nmf
new file mode 100644
index 0000000..3d6c02d
--- /dev/null
+++ b/platform_tools/nacl/skhello/skhello.nmf
@@ -0,0 +1,6 @@
+{
+ "program": {
+ "x86-64": {"url": "../../out/nacl64/Debug/skhello"},
+ "x86-32": {"url": "../../out/nacl32/Debug/skhello"}
+ }
+}
diff --git a/platform_tools/nacl/src/nacl_hello.cpp b/platform_tools/nacl/src/nacl_hello.cpp
new file mode 100644
index 0000000..a091ab4
--- /dev/null
+++ b/platform_tools/nacl/src/nacl_hello.cpp
@@ -0,0 +1,150 @@
+
+/*
+ * 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<SkiaInstance*>(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