Copy NaCl directory into trunk/platform_tools, adjust paths
(SkipBuildbotRuns) R=djsollen@google.com Review URL: https://codereview.chromium.org/14771017 git-svn-id: http://skia.googlecode.com/svn/trunk@9008 2bbb7eff-a529-9590-31e7-b0007b416f81
@ -109,7 +109,7 @@
|
||||
'../src/utils',
|
||||
],
|
||||
'sources': [
|
||||
'../../nacl/src/nacl_debugger.cpp',
|
||||
'../platform_tools/nacl/src/nacl_debugger.cpp',
|
||||
],
|
||||
}, { # skia_os != "nacl"
|
||||
'include_dirs': [
|
||||
|
@ -12,7 +12,7 @@
|
||||
'../src/utils',
|
||||
],
|
||||
'sources': [
|
||||
'../../nacl/src/nacl_interface.cpp',
|
||||
'../platform_tools/nacl/src/nacl_interface.cpp',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
6
platform_tools/nacl/SampleApp/SampleApp.nmf
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"program": {
|
||||
"x86-64": {"url": "../../out/nacl64/Debug/SampleApp"},
|
||||
"x86-32": {"url": "../../out/nacl32/Debug/SampleApp"}
|
||||
}
|
||||
}
|
71
platform_tools/nacl/SampleApp/index.html
Normal file
@ -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 Sample App</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 Sample App</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=0 height=0
|
||||
src="SampleApp.nmf"
|
||||
type="application/x-nacl" />
|
||||
</div>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
172
platform_tools/nacl/debugger/debugger.css
Normal file
@ -0,0 +1,172 @@
|
||||
body {
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
background-color:#EEE;
|
||||
}
|
||||
|
||||
div.single-line {
|
||||
clear:both;
|
||||
}
|
||||
|
||||
div.column-set {
|
||||
width:100%;
|
||||
height:100%;
|
||||
display:table;
|
||||
vertical-align:top;
|
||||
border-collapse:collapse;
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
div.column {
|
||||
display:table-cell;
|
||||
vertical-align:top;
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
div.row-set {
|
||||
width:100%;
|
||||
height:100%;
|
||||
display:table;
|
||||
vertical-align:top;
|
||||
border-collapse:collapse;
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
div.row {
|
||||
display:table-row;
|
||||
vertical-align:top;
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
height:5px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#left_column {
|
||||
width:230px;
|
||||
}
|
||||
|
||||
#command_list_div {
|
||||
}
|
||||
|
||||
#command_list_form {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#command_list {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#bottom_row {
|
||||
height:275px;
|
||||
}
|
||||
|
||||
#display_pane {
|
||||
}
|
||||
|
||||
#right_panel {
|
||||
width:230px;
|
||||
}
|
||||
|
||||
#tabview {
|
||||
}
|
||||
|
||||
#matrixclip {
|
||||
}
|
||||
|
||||
#small_window {
|
||||
width:218px;
|
||||
height:218px;
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
div.thin_outline {
|
||||
border:1px solid;
|
||||
margin:6px;
|
||||
padding:8px;
|
||||
}
|
||||
|
||||
div.settings_block {
|
||||
}
|
||||
|
||||
input.matrix {
|
||||
width:50px;
|
||||
}
|
||||
|
||||
#overviewdetails {
|
||||
width:100%;
|
||||
height:100%;
|
||||
resize:none;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
#menu {
|
||||
height:5px;
|
||||
overflow:auto;
|
||||
background-color:#999;
|
||||
}
|
||||
|
||||
#menu-bar {
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
ul.dropdown-menu a {
|
||||
display:block;
|
||||
text-decoration:none;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
ul.dropdown-menu, ul.dropdown-menu li, ul.dropdown-menu ul {
|
||||
list-style:none;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
}
|
||||
|
||||
ul.dropdown-menu {
|
||||
position:relative;
|
||||
z-index:597;
|
||||
float:left;
|
||||
}
|
||||
|
||||
ul.dropdown-menu li {
|
||||
float:left;
|
||||
padding:5px;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
ul.dropdown-menu li.hover, ul.dropdown-menu li:hover {
|
||||
position:relative;
|
||||
z-index:599;
|
||||
cursor:default;
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
ul.dropdown-menu ul {
|
||||
visibility:hidden;
|
||||
position:absolute;
|
||||
top:100%;
|
||||
left:0;
|
||||
z-index:598;
|
||||
width:195px;
|
||||
border:1px solid;
|
||||
border-collapse:collapse;
|
||||
background-color:#DDD;
|
||||
}
|
||||
|
||||
ul.dropdown-menu ul li {
|
||||
float:none;
|
||||
}
|
||||
|
||||
ul.dropdown-menu ul ul {
|
||||
top:-2px;
|
||||
left:100%;
|
||||
}
|
||||
|
||||
ul.dropdown-menu li:hover > ul {
|
||||
visibility:visible;
|
||||
}
|
6
platform_tools/nacl/debugger/debugger.nmf
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"program": {
|
||||
"x86-64": {"url": "../../out/nacl64/Debug/debugger"},
|
||||
"x86-32": {"url": "../../out/nacl32/Debug/debugger"}
|
||||
}
|
||||
}
|
BIN
platform_tools/nacl/debugger/icons/blank.png
Normal file
After Width: | Height: | Size: 146 B |
BIN
platform_tools/nacl/debugger/icons/breakpoint.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
platform_tools/nacl/debugger/icons/breakpoint_16x16.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
platform_tools/nacl/debugger/icons/delete.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
platform_tools/nacl/debugger/icons/inspector.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
platform_tools/nacl/debugger/icons/next.png
Normal file
After Width: | Height: | Size: 938 B |
BIN
platform_tools/nacl/debugger/icons/pause.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
platform_tools/nacl/debugger/icons/play.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
platform_tools/nacl/debugger/icons/previous.png
Normal file
After Width: | Height: | Size: 943 B |
BIN
platform_tools/nacl/debugger/icons/profile.png
Normal file
After Width: | Height: | Size: 243 B |
BIN
platform_tools/nacl/debugger/icons/reload.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
platform_tools/nacl/debugger/icons/rewind.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
platform_tools/nacl/debugger/icons/skia.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
468
platform_tools/nacl/debugger/index.html
Normal file
@ -0,0 +1,468 @@
|
||||
<!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 Debugger</title>
|
||||
<link rel="stylesheet" type="text/css" href="debugger.css"/>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
var skia_module = null; // Global application object.
|
||||
var display_right_panel = null;
|
||||
var display_bottom_row = null;
|
||||
var overview_text = "";
|
||||
var details_text = "Default details text.";
|
||||
var command_list = [];
|
||||
var command_types = {};
|
||||
var no_filter_text = "--Filter By Available Commands--";
|
||||
|
||||
function openFileDialog() {
|
||||
var event = document.createEvent("MouseEvents");
|
||||
event.initEvent("click", true, false);
|
||||
document.getElementById("file_open").dispatchEvent(event);
|
||||
}
|
||||
|
||||
function updateOverviewDetails() {
|
||||
var radio_buttons = document.getElementsByName("overviewdetails_radio");
|
||||
for (var i = 0; i < radio_buttons.length; ++i) {
|
||||
if (radio_buttons[i].checked) {
|
||||
if (radio_buttons[i].value == "details") {
|
||||
document.getElementById("overviewdetails").innerHTML = details_text;
|
||||
} else {
|
||||
document.getElementById("overviewdetails").innerHTML = overview_text;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If no radio button is checked, check the "overview" button.
|
||||
for (var i = 0; i < radio_buttons.length; ++i) {
|
||||
if (radio_buttons[i].value == "overview") {
|
||||
radio_buttons[i].checked = true;
|
||||
document.getElementById("overviewdetails").innerHTML = overview_text;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeIndentString(indent_amt) {
|
||||
var indent_str = "";
|
||||
for (var i = 0; i < indent_amt; ++i) {
|
||||
indent_str += "--";
|
||||
}
|
||||
return indent_str;
|
||||
}
|
||||
|
||||
function updateCommandList(filter) {
|
||||
var command_list_display = document.getElementById("command_list");
|
||||
command_list_display.options.length = 0;
|
||||
var indent = 0;
|
||||
var indent_str = "";
|
||||
for (var i = 0; i < command_list.length; ++i) {
|
||||
if (command_list[i] == "Restore") {
|
||||
indent--;
|
||||
indent_str = makeIndentString(indent);
|
||||
}
|
||||
if (!filter || filter == no_filter_text || command_list[i] == filter) {
|
||||
command_list_display.options.add(new Option(indent_str + command_list[i], i));
|
||||
}
|
||||
if (command_list[i] == "Save" || command_list[i] == "Save Layer") {
|
||||
indent++;
|
||||
indent_str = makeIndentString(indent);
|
||||
}
|
||||
}
|
||||
command_list_display.selectedIndex = command_list_display.length - 1;
|
||||
|
||||
// TODO(borenet): Should the SKP re-draw when the command list is updated?
|
||||
//commandSelected();
|
||||
}
|
||||
|
||||
function updateFilterList() {
|
||||
var filter_list_display = document.getElementById("command_filter");
|
||||
filter_list_display.options.length = 0;
|
||||
filter_list_display.options.add(new Option(no_filter_text, no_filter_text));
|
||||
for (var command_type in command_types) {
|
||||
if (command_types.hasOwnProperty(command_type)) {
|
||||
filter_list_display.options.add(new Option(command_type, command_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openFile(event) {
|
||||
document.getElementById("overviewdetails").innerHTML = "";
|
||||
var files = event.target.files;
|
||||
if (files.length != 1) {
|
||||
return;
|
||||
}
|
||||
var file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile) {
|
||||
return function(e) {
|
||||
var data_prefix = "data:;base64,";
|
||||
skia_module.postMessage("LoadSKP" + e.target.result.slice(data_prefix.length));
|
||||
};
|
||||
})(file);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
function toggleInspector() {
|
||||
var right_panel = document.getElementById("right_panel");
|
||||
var bottom_row = document.getElementById("bottom_row");
|
||||
if (right_panel.style.display == display_right_panel) {
|
||||
right_panel.style.display = "none";
|
||||
bottom_row.style.display = "none";
|
||||
} else {
|
||||
right_panel.style.display = display_right_panel;
|
||||
bottom_row.style.display = display_bottom_row;
|
||||
}
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
document.getElementById("file_open").addEventListener("change", openFile, false);
|
||||
var right_panel = document.getElementById("right_panel");
|
||||
var bottom_row = document.getElementById("bottom_row");
|
||||
display_right_panel = right_panel.style.display;
|
||||
display_bottom_row = bottom_row.style.display;
|
||||
updateOverviewDetails();
|
||||
updateFilterList();
|
||||
}
|
||||
|
||||
// When the module loads, begin running the application.
|
||||
function moduleDidLoad() {
|
||||
skia_module = document.getElementById("skia_nacl");
|
||||
sendMsg("init");
|
||||
}
|
||||
|
||||
function handleMessage(message_event) {
|
||||
var cmd_skdebugf = "SkDebugf:";
|
||||
var cmd_clear_commands = "ClearCommands";
|
||||
var cmd_add_command = "AddCommand:";
|
||||
var cmd_update_commands = "UpdateCommands";
|
||||
var cmd_set_overview = "SetOverview:";
|
||||
var cmd_add_filter_option = "AddFilterOption";
|
||||
if (message_event.data.indexOf(cmd_skdebugf) == 0) {
|
||||
var msg_contents = message_event.data.slice(cmd_skdebugf.length)
|
||||
console.log("Skia: " + msg_contents);
|
||||
} else if (message_event.data.indexOf(cmd_clear_commands) == 0) {
|
||||
command_list = [];
|
||||
command_types = {};
|
||||
updateCommandList();
|
||||
updateFilterList();
|
||||
} else if (message_event.data.indexOf(cmd_add_command) == 0) {
|
||||
var command = message_event.data.slice(cmd_add_command.length);
|
||||
command_list.push(command);
|
||||
if (command_types[command] == undefined) {
|
||||
command_types[command] = 1;
|
||||
} else {
|
||||
command_types[command]++;
|
||||
}
|
||||
} else if (message_event.data.indexOf(cmd_update_commands) == 0) {
|
||||
updateCommandList();
|
||||
updateFilterList();
|
||||
} else if (message_event.data.indexOf(cmd_set_overview) == 0) {
|
||||
overview_text = message_event.data.slice(cmd_set_overview.length);
|
||||
document.getElementById("overview_radio").checked = true;
|
||||
updateOverviewDetails();
|
||||
} else {
|
||||
alert(message_event.data);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a message to the plugin.
|
||||
function sendMsg(msg) {
|
||||
if (skia_module) {
|
||||
//console.log("Sending msg:" + msg);
|
||||
skia_module.postMessage(msg);
|
||||
} else {
|
||||
alert("The Skia module has not properly loaded...");
|
||||
}
|
||||
}
|
||||
|
||||
function commandSelected() {
|
||||
var command_list = document.getElementById("command_list");
|
||||
var selected_index = command_list.options[command_list.selectedIndex].value;
|
||||
if (selected_index >= 0) {
|
||||
sendMsg("CommandSelected:" + selected_index);
|
||||
}
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
command_list.selectedIndex = 0;
|
||||
sendMsg("Rewind");
|
||||
}
|
||||
|
||||
function stepBack() {
|
||||
if (command_list.selectedIndex > 0) {
|
||||
command_list.selectedIndex = command_list.selectedIndex - 1;
|
||||
}
|
||||
sendMsg("StepBack");
|
||||
}
|
||||
|
||||
function pause() {
|
||||
sendMsg("Pause");
|
||||
}
|
||||
|
||||
function stepForward() {
|
||||
if (command_list.selectedIndex < command_list.length - 1) {
|
||||
command_list.selectedIndex = command_list.selectedIndex + 1;
|
||||
}
|
||||
sendMsg("StepForward");
|
||||
}
|
||||
|
||||
function play() {
|
||||
command_list.selectedIndex = command_list.length - 1;
|
||||
sendMsg("Play");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onLoad="javascript:onLoad()">
|
||||
<div id="content" class="row-set">
|
||||
<div id="menu" class="row">
|
||||
<ul id="menu-bar" class="dropdown-menu">
|
||||
<li><a href="#">File</a>
|
||||
<ul>
|
||||
<li><a href="#" onClick="javascript:openFileDialog()">Open</a></li>
|
||||
<li><a href="#">Save</a></li>
|
||||
<li><a href="#">Save As</a></li>
|
||||
<li><a href="#">Exit</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Edit</a>
|
||||
<ul>
|
||||
<li><a href="#">Delete Command</a></li>
|
||||
<li><a href="#">Clear Deletes</a></li>
|
||||
<li><a href="#">Set Breakpoint</a></li>
|
||||
<li><a href="#">Clear Breakpoints</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">View</a>
|
||||
<ul>
|
||||
<li><a href="#">Breakpoints</a></li>
|
||||
<li><a href="#">Deleted Commands</a></li>
|
||||
<li><a href="#">Zoom In</a></li>
|
||||
<li><a href="#">Zoom Out</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Navigate</a>
|
||||
<ul>
|
||||
<li><a href="#" onClick="javascript:rewind()">Rewind</a></li>
|
||||
<li><a href="#" onClick="javascript:stepBack()">Step Back</a></li>
|
||||
<li><a href="#" onClick="javascript:stepForward()">Step Forward</a></li>
|
||||
<li><a href="#" onClick="javascript:play()">Play</a></li>
|
||||
<li><a href="#" onClick="javascript:pause()">Pause</a></li>
|
||||
<li><a href="#">Go to Line...</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Window</a>
|
||||
<ul>
|
||||
<li><a href="#">Inspector</a></li>
|
||||
<li><a href="#">Directory</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="buttons" class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">
|
||||
<button onClick="javascript:rewind()"><img src="icons/rewind.png"/><br/>Rewind</button>
|
||||
<button onClick="javascript:stepBack()"><img src="icons/previous.png"/><br/>Step Back</button>
|
||||
<button onClick="javascript:pause()"><img src="icons/pause.png"/><br/>Pause</button>
|
||||
<button onClick="javascript:stepForward()"><img src="icons/next.png"/><br/>Step Forward</button>
|
||||
<button onClick="javascript:play()"><img src="icons/play.png"/><br/>Play</button>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button onClick="javascript:toggleInspector()"><img src="icons/inspector.png"/><br/>Inspector</button>
|
||||
</div>
|
||||
<div class="column">
|
||||
<button><img src="icons/profile.png"/><br/>Profile</button>
|
||||
</div>
|
||||
<div class="column" style="text-align:right; vertical-align:middle;">
|
||||
<select id="command_filter" onChange="javascript:updateCommandList(this.options[this.selectedIndex].value)"></select>
|
||||
<button onClick="javascript:updateCommandList()"><img src="icons/reload.png" /><br/>Clear Filter</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div id="left_column" class="column">
|
||||
<div class="row-set">
|
||||
<div id="command_list_div" class="row">
|
||||
<form id="command_list_form">
|
||||
<select id="command_list" size="2" onChange="javascript:commandSelected()">
|
||||
<option value="-1">Commands go here...</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="right_column" class="row-set">
|
||||
<div id="top_row" class="row">
|
||||
<div id="display_pane" class="column">
|
||||
<div id="listener" style="width:100%; height:100%;">
|
||||
<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"
|
||||
src="debugger.nmf"
|
||||
type="application/x-nacl"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style="width:100%, height:100%;"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="right_panel" class="column">
|
||||
<div class="thin_outline">
|
||||
<div id="visibility_filter" class="settings_block">
|
||||
Visibility Filter<br/>
|
||||
<div class="thin_outline">
|
||||
<form id="visibility_filter_form">
|
||||
<input type="radio" name="visibility_filter_radio" value="on">On<br/>
|
||||
<input type="radio" name="visibility_filter_radio" value="off" checked>Off
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="command_scrolling" class="settings_block">
|
||||
Command Scrolling Preferences<br/>
|
||||
<div class="thin_outline">
|
||||
<div class="row-set">
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">
|
||||
Current Command:
|
||||
</div>
|
||||
<div class="column" style="text-align:right; width:35%;">
|
||||
<input type="text" style="width:100%;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">
|
||||
Command HitBox:
|
||||
</div>
|
||||
<div class="column" style="text-align:right; width:35%;">
|
||||
<input type="text" style="width:100%;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="render_targets" class="settings_block">
|
||||
Render Targets<br/>
|
||||
<div class="thin_outline">
|
||||
<form id="render_targets_form">
|
||||
<div class="row-set">
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">Raster:</div>
|
||||
<div class="column" style="text-align:right;">
|
||||
<input type="checkbox" name="render_targets_checkbox" value="raster" checked/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column" style="padding-left:30px;">Overdraw Viz:</div>
|
||||
<div class="column" style="text-align:right;">
|
||||
<input type="checkbox" name="render_targets_checkbox" value="overdraw"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">OpenGL</div>
|
||||
<div class="column" style="text-align:right;">
|
||||
<input type="checkbox" name="render_targets_checkbox" value="opengl"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="zoom_level" class="settings_block">
|
||||
<div class="thin_outline">
|
||||
<div class="row-set">
|
||||
<div class="row">
|
||||
<div class="column-set">
|
||||
<div class="column">
|
||||
Zoom Level:
|
||||
</div>
|
||||
<div class="column" style="text-align:right; width:35%;">
|
||||
<input type="text" style="width:100%;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="small_window_wrapper" class="settings_block">
|
||||
<div class="thin_outline" style="padding:0px;">
|
||||
<div id="small_window">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom_row" class="row">
|
||||
<div id="tabview" class="column">
|
||||
<div class="row-set">
|
||||
<div class="row" style="height:5px; overflow:auto;">
|
||||
<form id="overviewdetails_form">
|
||||
<input type="radio" name="overviewdetails_radio" onChange="javascript:updateOverviewDetails()" id="overview_radio" value="overview" checked>Overview
|
||||
<input type="radio" name="overviewdetails_radio" onChange="javascript:updateOverviewDetails()" id="details_radio" value="details">Details
|
||||
</form>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="overviewdetails"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="matrixclip" class="column">
|
||||
Current Matrix
|
||||
<table>
|
||||
<tr>
|
||||
<td><input type="text" id="matrix00" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix01" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix02" class="matrix" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="text" id="matrix10" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix11" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix12" class="matrix" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="text" id="matrix20" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix21" class="matrix" /></td>
|
||||
<td><input type="text" id="matrix22" class="matrix" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
Current Clip
|
||||
<table>
|
||||
<tr>
|
||||
<td><input type="text" id="clip00" class="matrix" /></td>
|
||||
<td><input type="text" id="clip01" class="matrix" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="text" id="clip10" class="matrix" /></td>
|
||||
<td><input type="text" id="clip11" class="matrix" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" id="file_open" style="display:none;"/>
|
||||
</body>
|
||||
</html>
|
BIN
platform_tools/nacl/favicon.ico
Normal file
After Width: | Height: | Size: 318 B |
13
platform_tools/nacl/gclient.config
Normal file
@ -0,0 +1,13 @@
|
||||
# To develop Skia targeting NaCl,
|
||||
# copy this file to your root development directory as ".gclient"
|
||||
# and then run "gclient sync".
|
||||
solutions = [
|
||||
{
|
||||
"name" : "nacl",
|
||||
"url" : "https://skia.googlecode.com/svn/nacl",
|
||||
},
|
||||
{
|
||||
"name" : "trunk",
|
||||
"url" : "https://skia.googlecode.com/svn/trunk",
|
||||
},
|
||||
]
|
212
platform_tools/nacl/httpd.py
Executable file
@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""A tiny web server.
|
||||
|
||||
This is intended to be used for testing, and only run from within the examples
|
||||
directory.
|
||||
"""
|
||||
|
||||
import BaseHTTPServer
|
||||
import logging
|
||||
import optparse
|
||||
import os
|
||||
import SimpleHTTPServer
|
||||
import SocketServer
|
||||
import sys
|
||||
import urlparse
|
||||
|
||||
|
||||
EXAMPLE_PATH=os.path.dirname(os.path.abspath(__file__))
|
||||
NACL_SDK_ROOT = os.getenv('NACL_SDK_ROOT', os.path.dirname(EXAMPLE_PATH))
|
||||
|
||||
|
||||
if os.path.exists(NACL_SDK_ROOT):
|
||||
sys.path.append(os.path.join(NACL_SDK_ROOT, 'tools'))
|
||||
import decode_dump
|
||||
import getos
|
||||
else:
|
||||
NACL_SDK_ROOT=None
|
||||
|
||||
last_nexe = None
|
||||
last_nmf = None
|
||||
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
# Using 'localhost' means that we only accept connections
|
||||
# via the loop back interface.
|
||||
SERVER_PORT = 5103
|
||||
SERVER_HOST = ''
|
||||
|
||||
# We only run from the examples directory so that not too much is exposed
|
||||
# via this HTTP server. Everything in the directory is served, so there should
|
||||
# never be anything potentially sensitive in the serving directory, especially
|
||||
# if the machine might be a multi-user machine and not all users are trusted.
|
||||
# We only serve via the loopback interface.
|
||||
def SanityCheckDirectory():
|
||||
httpd_path = os.path.abspath(os.path.dirname(__file__))
|
||||
serve_path = os.path.abspath(os.getcwd())
|
||||
|
||||
# Verify we are serving from the directory this script came from, or bellow
|
||||
if serve_path[:len(httpd_path)] == httpd_path:
|
||||
return
|
||||
logging.error('For security, httpd.py should only be run from within the')
|
||||
logging.error('example directory tree.')
|
||||
logging.error('We are currently in %s.' % serve_path)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# An HTTP server that will quit when |is_running| is set to False. We also use
|
||||
# SocketServer.ThreadingMixIn in order to handle requests asynchronously for
|
||||
# faster responses.
|
||||
class QuittableHTTPServer(SocketServer.ThreadingMixIn,
|
||||
BaseHTTPServer.HTTPServer):
|
||||
def serve_forever(self, timeout=0.5):
|
||||
self.is_running = True
|
||||
self.timeout = timeout
|
||||
while self.is_running:
|
||||
self.handle_request()
|
||||
|
||||
def shutdown(self):
|
||||
self.is_running = False
|
||||
return 1
|
||||
|
||||
|
||||
# "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not
|
||||
# exist in |str|, then the entire |str| is the key and the value is set to an
|
||||
# empty string.
|
||||
def KeyValuePair(str, sep='='):
|
||||
if sep in str:
|
||||
return str.split(sep)
|
||||
else:
|
||||
return [str, '']
|
||||
|
||||
|
||||
# A small handler that looks for '?quit=1' query in the path and shuts itself
|
||||
# down if it finds that parameter.
|
||||
class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
def send_head(self):
|
||||
"""Common code for GET and HEAD commands.
|
||||
|
||||
This sends the response code and MIME headers.
|
||||
|
||||
Return value is either a file object (which has to be copied
|
||||
to the outputfile by the caller unless the command was HEAD,
|
||||
and must be closed by the caller under all circumstances), or
|
||||
None, in which case the caller has nothing further to do.
|
||||
|
||||
"""
|
||||
path = self.translate_path(self.path)
|
||||
f = None
|
||||
if os.path.isdir(path):
|
||||
if not self.path.endswith('/'):
|
||||
# redirect browser - doing basically what apache does
|
||||
self.send_response(301)
|
||||
self.send_header("Location", self.path + "/")
|
||||
self.end_headers()
|
||||
return None
|
||||
for index in "index.html", "index.htm":
|
||||
index = os.path.join(path, index)
|
||||
if os.path.exists(index):
|
||||
path = index
|
||||
break
|
||||
else:
|
||||
return self.list_directory(path)
|
||||
ctype = self.guess_type(path)
|
||||
try:
|
||||
# Always read in binary mode. Opening files in text mode may cause
|
||||
# newline translations, making the actual size of the content
|
||||
# transmitted *less* than the content-length!
|
||||
f = open(path, 'rb')
|
||||
except IOError:
|
||||
self.send_error(404, "File not found")
|
||||
return None
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", ctype)
|
||||
fs = os.fstat(f.fileno())
|
||||
self.send_header("Content-Length", str(fs[6]))
|
||||
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
|
||||
self.send_header('Cache-Control','no-cache, must-revalidate')
|
||||
self.send_header('Expires','-1')
|
||||
self.end_headers()
|
||||
return f
|
||||
|
||||
def do_GET(self):
|
||||
global last_nexe, last_nmf
|
||||
(_, _, path, query, _) = urlparse.urlsplit(self.path)
|
||||
url_params = dict([KeyValuePair(key_value)
|
||||
for key_value in query.split('&')])
|
||||
if 'quit' in url_params and '1' in url_params['quit']:
|
||||
self.send_response(200, 'OK')
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.send_header('Content-length', '0')
|
||||
self.end_headers()
|
||||
self.server.shutdown()
|
||||
return
|
||||
|
||||
if path.endswith('.nexe'):
|
||||
last_nexe = path
|
||||
if path.endswith('.nmf'):
|
||||
last_nmf = path
|
||||
|
||||
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
def do_POST(self):
|
||||
(_, _,path, query, _) = urlparse.urlsplit(self.path)
|
||||
if 'Content-Length' in self.headers:
|
||||
if not NACL_SDK_ROOT:
|
||||
self.wfile('Could not find NACL_SDK_ROOT to decode trace.')
|
||||
return
|
||||
data = self.rfile.read(int(self.headers['Content-Length']))
|
||||
nexe = '.' + last_nexe
|
||||
nmf = '.' + last_nmf
|
||||
addr = os.path.join(NACL_SDK_ROOT, 'toolchain',
|
||||
getos.GetPlatform() + '_x86_newlib',
|
||||
'bin', 'x86_64-nacl-addr2line')
|
||||
decoder = decode_dump.CoreDecoder(nexe, nmf, addr, None, None)
|
||||
info = decoder.Decode(data)
|
||||
trace = decoder.StackTrace(info)
|
||||
decoder.PrintTrace(trace, sys.stdout)
|
||||
decoder.PrintTrace(trace, self.wfile)
|
||||
|
||||
|
||||
def Run(server_address,
|
||||
server_class=QuittableHTTPServer,
|
||||
handler_class=QuittableHTTPHandler):
|
||||
httpd = server_class(server_address, handler_class)
|
||||
logging.info("Starting local server on port %d", server_address[1])
|
||||
logging.info("To shut down send http://localhost:%d?quit=1",
|
||||
server_address[1])
|
||||
try:
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Received keyboard interrupt.")
|
||||
httpd.server_close()
|
||||
|
||||
logging.info("Shutting down local server on port %d", server_address[1])
|
||||
|
||||
|
||||
def main():
|
||||
usage_str = "usage: %prog [options] [optional_portnum]"
|
||||
parser = optparse.OptionParser(usage=usage_str)
|
||||
parser.add_option(
|
||||
'--no_dir_check', dest='do_safe_check',
|
||||
action='store_false', default=True,
|
||||
help='Do not ensure that httpd.py is being run from a safe directory.')
|
||||
(options, args) = parser.parse_args(sys.argv)
|
||||
if options.do_safe_check:
|
||||
SanityCheckDirectory()
|
||||
if len(args) > 2:
|
||||
print 'Too many arguments specified.'
|
||||
parser.print_help()
|
||||
elif len(args) == 2:
|
||||
Run((SERVER_HOST, int(args[1])))
|
||||
else:
|
||||
Run((SERVER_HOST, SERVER_PORT))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
22
platform_tools/nacl/index.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!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 Native Client Apps</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Skia Native Client Apps</h1>
|
||||
<p>
|
||||
<ul>
|
||||
<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>
|
||||
</ul>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
104
platform_tools/nacl/nacl_make
Executable file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
|
||||
function setenv {
|
||||
if [ -z "$1" ]; then
|
||||
echo "ERROR: setenv() requires one argument."
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${NACL_SDK_ROOT}" ]; then
|
||||
echo "ERROR: This script requires NACL_SDK_ROOT to be set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ARCH_WIDTH=$1
|
||||
if [ ${ARCH_WIDTH} = "32" ]; then
|
||||
CROSS_ID=i686
|
||||
elif [ ${ARCH_WIDTH} = "64" ]; then
|
||||
CROSS_ID=x86_64
|
||||
else
|
||||
echo "ERROR: Unknown arch width: ${ARCH_WIDTH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OS_NAME=$(uname -s)
|
||||
if [ $OS_NAME = "Darwin" ]; then
|
||||
OS_SUBDIR="mac"
|
||||
OS_SUBDIR_SHORT="mac"
|
||||
OS_JOBS=4
|
||||
elif [ $OS_NAME = "Linux" ]; then
|
||||
OS_SUBDIR="linux"
|
||||
OS_SUBDIR_SHORT="linux"
|
||||
OS_JOBS=4
|
||||
else
|
||||
OS_SUBDIR="windows"
|
||||
OS_SUBDIR_SHORT="win"
|
||||
OS_JOBS=1
|
||||
fi
|
||||
|
||||
NACL_TOOLCHAIN_ROOT=${NACL_SDK_ROOT}/toolchain/${OS_SUBDIR_SHORT}_x86_newlib
|
||||
NACL_BIN_PATH=${NACL_TOOLCHAIN_ROOT}/bin
|
||||
export NACL_CROSS_PREFIX=${CROSS_ID}-nacl
|
||||
|
||||
if [[ -z "$NACL_MAKE_CCACHE" ]]; then
|
||||
export NACLCC=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-gcc
|
||||
export NACLCXX=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-g++
|
||||
else
|
||||
export NACLCC="${NACL_MAKE_CCACHE} ${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-gcc"
|
||||
export NACLCXX="${NACL_MAKE_CCACHE} ${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-g++"
|
||||
fi
|
||||
export NACLAR=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-ar
|
||||
export NACLRANLIB=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-ranlib
|
||||
export NACLLD=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-ld
|
||||
export NACLSTRINGS=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-strings
|
||||
export NACLSTRIP=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX}-strip
|
||||
|
||||
export CC=${NACLCC}
|
||||
export CXX=${NACLCXX}
|
||||
export AR=${NACLAR}
|
||||
export RANLIB=${NACLRANLIB}
|
||||
export PATH=${NACL_BIN_PATH}:${PATH};
|
||||
|
||||
export GYP_DEFINES="skia_os=nacl skia_arch_width=${ARCH_WIDTH}"
|
||||
}
|
||||
|
||||
function build {
|
||||
if [ -z "$1" ]; then
|
||||
echo "ERROR: build() requires one argument."
|
||||
exit 1
|
||||
fi
|
||||
setenv $1
|
||||
|
||||
export SKIA_OUT=out/nacl$1
|
||||
make ${MAKE_ARGS}
|
||||
}
|
||||
|
||||
MAKE_ARGS=""
|
||||
|
||||
while (( "$#" )); do
|
||||
if [[ "$1" == "--use-ccache" ]];
|
||||
then
|
||||
if [[ -z "$NACL_MAKE_CCACHE" ]];
|
||||
then
|
||||
NACL_MAKE_CCACHE=$(which ccache)
|
||||
fi
|
||||
elif [ -z "${MAKE_ARGS}" ]; then
|
||||
MAKE_ARGS="$1"
|
||||
else
|
||||
MAKE_ARGS="${MAKE_ARGS} $1"
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -n "$NACL_MAKE_CCACHE" ]]; then
|
||||
$NACL_MAKE_CCACHE --version &> /dev/null
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Unable to find ccache!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
build 32 && \
|
||||
build 64 && \
|
||||
if ! [ -L platform_tools/nacl/out ]; then
|
||||
ln -s ../../out platform_tools/nacl
|
||||
fi
|
221
platform_tools/nacl/src/nacl_debugger.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
|
||||
/*
|
||||
* 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 "SkBase64.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColor.h"
|
||||
#include "SkDebugger.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
|
||||
class SkiaInstance;
|
||||
|
||||
// Used by SkDebugf
|
||||
SkiaInstance* gPluginInstance;
|
||||
|
||||
void FlushCallback(void* data, int32_t result);
|
||||
|
||||
// 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)
|
||||
, fPicture(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.
|
||||
if (var_message.is_string()) {
|
||||
SkString msg(var_message.AsString().c_str());
|
||||
if (msg.startsWith("init")) {
|
||||
} else if (msg.startsWith("LoadSKP")) {
|
||||
size_t startIndex = strlen("LoadSKP");
|
||||
size_t dataSize = msg.size()/sizeof(char) - startIndex;
|
||||
SkBase64 decodedData;
|
||||
decodedData.decode(msg.c_str() + startIndex, dataSize);
|
||||
size_t decodedSize = 3 * (dataSize / 4);
|
||||
SkDebugf("Got size: %d\n", decodedSize);
|
||||
if (!decodedData.getData()) {
|
||||
SkDebugf("Failed to decode SKP\n");
|
||||
return;
|
||||
}
|
||||
SkMemoryStream pictureStream(decodedData.getData(), decodedSize);
|
||||
fPicture = new SkPicture(&pictureStream);
|
||||
if (fPicture->width() == 0 || fPicture->height() == 0) {
|
||||
SkDebugf("Failed to create SKP.\n");
|
||||
return;
|
||||
}
|
||||
fDebugger.loadPicture(fPicture);
|
||||
|
||||
// Set up the command list.
|
||||
SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings();
|
||||
PostMessage("ClearCommands");
|
||||
for (int i = 0; i < commands->count(); ++i) {
|
||||
SkString addCommand("AddCommand:");
|
||||
addCommand.append((*commands)[i]);
|
||||
PostMessage(addCommand.c_str());
|
||||
}
|
||||
PostMessage("UpdateCommands");
|
||||
|
||||
// Set the overview text.
|
||||
SkString overviewText;
|
||||
fDebugger.getOverviewText(NULL, 0.0, &overviewText, 1);
|
||||
overviewText.prepend("SetOverview:");
|
||||
PostMessage(overviewText.c_str());
|
||||
|
||||
// Draw the SKP.
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
} else if (msg.startsWith("CommandSelected:")) {
|
||||
size_t startIndex = strlen("CommandSelected:");
|
||||
int index = atoi(msg.c_str() + startIndex);
|
||||
fDebugger.setIndex(index);
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
} else if (msg.startsWith("Rewind")) {
|
||||
fCanvas->clear(SK_ColorWHITE);
|
||||
fDebugger.setIndex(0);
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
} else if (msg.startsWith("StepBack")) {
|
||||
fCanvas->clear(SK_ColorWHITE);
|
||||
int currentIndex = fDebugger.index();
|
||||
if (currentIndex > 1) {
|
||||
fDebugger.setIndex(currentIndex - 1);
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
}
|
||||
} else if (msg.startsWith("Pause")) {
|
||||
// TODO(borenet)
|
||||
} else if (msg.startsWith("StepForward")) {
|
||||
int currentIndex = fDebugger.index();
|
||||
if (currentIndex < fDebugger.getSize() -1) {
|
||||
fDebugger.setIndex(currentIndex + 1);
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
}
|
||||
} else if (msg.startsWith("Play")) {
|
||||
fDebugger.setIndex(fDebugger.getSize() - 1);
|
||||
if (!fFlushLoopRunning) {
|
||||
Paint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Paint() {
|
||||
if (!fImage.is_null()) {
|
||||
fDebugger.draw(fCanvas);
|
||||
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;
|
||||
SkDebugger fDebugger;
|
||||
SkPicture* fPicture;
|
||||
|
||||
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
|
111
platform_tools/nacl/src/nacl_interface.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
|
||||
/*
|
||||
* 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/var.h"
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkString.h"
|
||||
#include "SkThreadUtils.h"
|
||||
|
||||
class SkiaInstance;
|
||||
|
||||
// Used by SkDebugf
|
||||
SkiaInstance* gPluginInstance;
|
||||
|
||||
// Main entry point for the app we're linked into
|
||||
extern int tool_main(int, char**);
|
||||
|
||||
// Tokenize a command line and store it in argc and argv.
|
||||
void SkStringToProgramArgs(const SkString commandLine, int* argc, char*** argv) {
|
||||
int numBreaks = 0;
|
||||
const char* commandChars = commandLine.c_str();
|
||||
for (size_t i = 0; i < strlen(commandChars); i++) {
|
||||
if (isspace(commandChars[i])) {
|
||||
numBreaks++;
|
||||
}
|
||||
}
|
||||
int numArgs;
|
||||
if (strlen(commandChars) > 0) {
|
||||
numArgs = numBreaks + 1;
|
||||
} else {
|
||||
numArgs = 0;
|
||||
}
|
||||
*argc = numArgs;
|
||||
*argv = new char*[numArgs + 1];
|
||||
(*argv)[numArgs] = NULL;
|
||||
char* start = (char*) commandChars;
|
||||
int length = 0;
|
||||
int argIndex = 0;
|
||||
for (size_t i = 0; i < strlen(commandChars) + 1; i++) {
|
||||
if (isspace(commandChars[i]) || '\0' == commandChars[i]) {
|
||||
if (length > 0) {
|
||||
char* argument = new char[length + 1];
|
||||
memcpy(argument, start, length);
|
||||
argument[length] = '\0';
|
||||
(*argv)[argIndex++] = argument;
|
||||
}
|
||||
start = (char*) commandChars + i + 1;
|
||||
length = 0;
|
||||
} else {
|
||||
length++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the program with the given command line.
|
||||
void RunProgram(const SkString& commandLine) {
|
||||
int argc;
|
||||
char** argv;
|
||||
SkStringToProgramArgs(commandLine, &argc, &argv);
|
||||
tool_main(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
gPluginInstance = this;
|
||||
}
|
||||
|
||||
virtual ~SkiaInstance() {
|
||||
gPluginInstance = NULL;
|
||||
}
|
||||
|
||||
virtual void HandleMessage(const pp::Var& var_message) {
|
||||
// Receive a message from javascript.
|
||||
if (var_message.is_string()) {
|
||||
SkString msg(var_message.AsString().c_str());
|
||||
if (msg.startsWith("init")) {
|
||||
RunProgram(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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
|
212
platform_tools/nacl/src/nacl_sample.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#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/var.h"
|
||||
|
||||
#include "SampleApp.h"
|
||||
#include "SkApplication.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkEvent.h"
|
||||
#include "SkWindow.h"
|
||||
|
||||
class SkiaInstance;
|
||||
|
||||
namespace {
|
||||
void FlushCallback(void* data, int32_t result);
|
||||
}
|
||||
|
||||
SkiaInstance* gPluginInstance;
|
||||
extern int main(int, char**);
|
||||
|
||||
class SkiaInstance : public pp::Instance {
|
||||
public:
|
||||
explicit SkiaInstance(PP_Instance instance) : pp::Instance(instance),
|
||||
fFlushPending(false),
|
||||
fGraphics2dContext(NULL),
|
||||
fPixelBuffer(NULL)
|
||||
{
|
||||
gPluginInstance = this;
|
||||
application_init();
|
||||
char* commandName = "SampleApp";
|
||||
fWindow = new SampleWindow(NULL, 0, &commandName, NULL);
|
||||
}
|
||||
|
||||
virtual ~SkiaInstance() {
|
||||
gPluginInstance = NULL;
|
||||
delete fWindow;
|
||||
application_term();
|
||||
}
|
||||
|
||||
virtual void HandleMessage(const pp::Var& var_message) {
|
||||
// Receive a message from javascript. Right now this just signals us to
|
||||
// get started.
|
||||
uint32_t width = 500;
|
||||
uint32_t height = 500;
|
||||
char buffer[2048];
|
||||
sprintf(buffer, "SetSize:%d,%d", width, height);
|
||||
PostMessage(buffer);
|
||||
}
|
||||
|
||||
virtual void DidChangeView(const pp::Rect& position,
|
||||
const pp::Rect& clip) {
|
||||
if (position.size().width() == width() &&
|
||||
position.size().height() == height()) {
|
||||
return; // Size didn't change, no need to update anything.
|
||||
}
|
||||
// Create a new device context with the new size.
|
||||
DestroyContext();
|
||||
CreateContext(position.size());
|
||||
// Delete the old pixel buffer and create a new one.
|
||||
delete fPixelBuffer;
|
||||
fPixelBuffer = NULL;
|
||||
if (fGraphics2dContext != NULL) {
|
||||
fPixelBuffer = new pp::ImageData(this,
|
||||
PP_IMAGEDATAFORMAT_BGRA_PREMUL,
|
||||
fGraphics2dContext->size(),
|
||||
false);
|
||||
fWindow->resize(position.size().width(), position.size().height());
|
||||
fWindow->update(NULL);
|
||||
paint();
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate whether a flush is pending. This can only be called from the
|
||||
// main thread; it is not thread safe.
|
||||
bool flush_pending() const {
|
||||
return fFlushPending;
|
||||
}
|
||||
void set_flush_pending(bool flag) {
|
||||
fFlushPending = flag;
|
||||
}
|
||||
|
||||
void paint() {
|
||||
if (fPixelBuffer) {
|
||||
// Draw some stuff. TODO(borenet): Actually have SampleApp draw into
|
||||
// the plugin area.
|
||||
uint32_t w = fPixelBuffer->size().width();
|
||||
uint32_t h = fPixelBuffer->size().height();
|
||||
uint32_t* data = (uint32_t*) fPixelBuffer->data();
|
||||
// Create a bitmap using the fPixelBuffer pixels
|
||||
SkBitmap bitmap;
|
||||
bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
bitmap.setPixels(data);
|
||||
// Create a canvas with the bitmap as the backend
|
||||
SkCanvas canvas(bitmap);
|
||||
|
||||
canvas.drawColor(SK_ColorBLUE);
|
||||
SkRect rect = SkRect::MakeXYWH(10, 10, 80, 80);
|
||||
SkPaint rect_paint;
|
||||
rect_paint.setStyle(SkPaint::kFill_Style);
|
||||
rect_paint.setColor(SK_ColorRED);
|
||||
canvas.drawRect(rect, rect_paint);
|
||||
|
||||
FlushPixelBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int width() const {
|
||||
return fPixelBuffer ? fPixelBuffer->size().width() : 0;
|
||||
}
|
||||
|
||||
int height() const {
|
||||
return fPixelBuffer ? fPixelBuffer->size().height() : 0;
|
||||
}
|
||||
|
||||
bool IsContextValid() const {
|
||||
return fGraphics2dContext != NULL;
|
||||
}
|
||||
|
||||
void CreateContext(const pp::Size& size) {
|
||||
if (IsContextValid())
|
||||
return;
|
||||
fGraphics2dContext = new pp::Graphics2D(this, size, false);
|
||||
if (!BindGraphics(*fGraphics2dContext)) {
|
||||
SkDebugf("Couldn't bind the device context");
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyContext() {
|
||||
if (!IsContextValid())
|
||||
return;
|
||||
delete fGraphics2dContext;
|
||||
fGraphics2dContext = NULL;
|
||||
}
|
||||
|
||||
void FlushPixelBuffer() {
|
||||
if (!IsContextValid())
|
||||
return;
|
||||
// Note that the pixel lock is held while the buffer is copied into the
|
||||
// device context and then flushed.
|
||||
fGraphics2dContext->PaintImageData(*fPixelBuffer, pp::Point());
|
||||
if (flush_pending())
|
||||
return;
|
||||
set_flush_pending(true);
|
||||
fGraphics2dContext->Flush(pp::CompletionCallback(&FlushCallback, this));
|
||||
}
|
||||
|
||||
bool fFlushPending;
|
||||
pp::Graphics2D* fGraphics2dContext;
|
||||
pp::ImageData* fPixelBuffer;
|
||||
SampleWindow* fWindow;
|
||||
};
|
||||
|
||||
class SkiaModule : public pp::Module {
|
||||
public:
|
||||
SkiaModule() : pp::Module() {}
|
||||
virtual ~SkiaModule() {}
|
||||
|
||||
virtual pp::Instance* CreateInstance(PP_Instance instance) {
|
||||
gPluginInstance = new SkiaInstance(instance);
|
||||
return gPluginInstance;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
void FlushCallback(void* data, int32_t result) {
|
||||
static_cast<SkiaInstance*>(data)->set_flush_pending(false);
|
||||
}
|
||||
}
|
||||
|
||||
namespace pp {
|
||||
Module* CreateModule() {
|
||||
return new SkiaModule();
|
||||
}
|
||||
} // namespace pp
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
///////////// SkOSWindow impl /////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
void SkOSWindow::onSetTitle(const char title[])
|
||||
{
|
||||
char buffer[2048];
|
||||
sprintf(buffer, "SetTitle:%s", title);
|
||||
gPluginInstance->PostMessage(buffer);
|
||||
}
|
||||
|
||||
void SkOSWindow::onHandleInval(const SkIRect& rect)
|
||||
{
|
||||
gPluginInstance->paint();
|
||||
}
|
||||
|
||||
void SkOSWindow::onPDFSaved(const char title[], const char desc[],
|
||||
const char path[]) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
/////////////// SkEvent impl //////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
void SkEvent::SignalQueueTimer(SkMSec ms) {
|
||||
}
|
||||
|
||||
void SkEvent::SignalNonEmptyQueue() {
|
||||
}
|
78
platform_tools/nacl/tests/index.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!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 Unit Tests</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);
|
||||
var log_textarea = document.getElementById("log_textarea")
|
||||
log_textarea.value += msg_contents;
|
||||
log_textarea.scrollTop = log_textarea.scrollHeight;
|
||||
refresh(log_textarea);
|
||||
} 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 Unit Tests</h1>
|
||||
<p>
|
||||
<textarea id="log_textarea" rows="2" cols="2" readonly style="width:100%; height:500px; resize:none;"></textarea>
|
||||
</p>
|
||||
<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=0 height=0
|
||||
src="tests.nmf"
|
||||
type="application/x-nacl" />
|
||||
</div>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
6
platform_tools/nacl/tests/tests.nmf
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"program": {
|
||||
"x86-64": {"url": "../../out/nacl64/Debug/tests"},
|
||||
"x86-32": {"url": "../../out/nacl32/Debug/tests"}
|
||||
}
|
||||
}
|