Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: experimental/SkV8Example/SkV8Example.cpp

Issue 103143009: Add a setTimer() function. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « experimental/SkV8Example/SkV8Example.h ('k') | experimental/SkV8Example/sample.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 * 7 *
8 */ 8 */
9 #include <v8.h> 9 #include <v8.h>
10 10
11 using namespace v8; 11 using namespace v8;
12 12
13 #include "SkV8Example.h" 13 #include "SkV8Example.h"
14 #include "Global.h"
14 15
15 #include "gl/GrGLUtil.h" 16 #include "gl/GrGLUtil.h"
16 #include "gl/GrGLDefines.h" 17 #include "gl/GrGLDefines.h"
17 #include "gl/GrGLInterface.h" 18 #include "gl/GrGLInterface.h"
18 #include "SkApplication.h" 19 #include "SkApplication.h"
19 #include "SkCommandLineFlags.h" 20 #include "SkCommandLineFlags.h"
20 #include "SkData.h" 21 #include "SkData.h"
21 #include "SkDraw.h" 22 #include "SkDraw.h"
22 #include "SkGpuDevice.h" 23 #include "SkGpuDevice.h"
23 #include "SkGraphics.h" 24 #include "SkGraphics.h"
24 #include "SkScalar.h" 25 #include "SkScalar.h"
25 26
26 27
27 DEFINE_string2(infile, i, NULL, "Name of file to load JS from.\n"); 28 DEFINE_string2(infile, i, NULL, "Name of file to load JS from.\n");
28 29
29 void application_init() { 30 void application_init() {
30 SkGraphics::Init(); 31 SkGraphics::Init();
31 SkEvent::Init(); 32 SkEvent::Init();
32 } 33 }
33 34
34 void application_term() { 35 void application_term() {
35 SkEvent::Term(); 36 SkEvent::Term();
36 SkGraphics::Term(); 37 SkGraphics::Term();
37 } 38 }
38 39
39 // Extracts a C string from a V8 Utf8Value. 40 // Extracts a C string from a V8 Utf8Value.
40 const char* ToCString(const v8::String::Utf8Value& value) { 41 // TODO(jcgregrio) Currently dup'd in two files, fix.
42 static const char* to_cstring(const v8::String::Utf8Value& value) {
41 return *value ? *value : "<string conversion failed>"; 43 return *value ? *value : "<string conversion failed>";
42 } 44 }
43 45
44 // Slight modification to an original function found in the V8 sample shell.cc.
45 void reportException(Isolate* isolate, TryCatch* try_catch) {
46 HandleScope handleScope(isolate);
47 String::Utf8Value exception(try_catch->Exception());
48 const char* exception_string = ToCString(exception);
49 Handle<Message> message = try_catch->Message();
50 if (message.IsEmpty()) {
51 // V8 didn't provide any extra information about this error; just
52 // print the exception.
53 fprintf(stderr, "%s\n", exception_string);
54 } else {
55 // Print (filename):(line number): (message).
56 String::Utf8Value filename(message->GetScriptResourceName());
57 const char* filename_string = ToCString(filename);
58 int linenum = message->GetLineNumber();
59 fprintf(stderr,
60 "%s:%i: %s\n", filename_string, linenum, exception_string);
61 // Print line of source code.
62 String::Utf8Value sourceline(message->GetSourceLine());
63 const char* sourceline_string = ToCString(sourceline);
64 fprintf(stderr, "%s\n", sourceline_string);
65 // Print wavy underline.
66 int start = message->GetStartColumn();
67 for (int i = 0; i < start; i++) {
68 fprintf(stderr, " ");
69 }
70 int end = message->GetEndColumn();
71 for (int i = start; i < end; i++) {
72 fprintf(stderr, "^");
73 }
74 fprintf(stderr, "\n");
75 String::Utf8Value stack_trace(try_catch->StackTrace());
76 if (stack_trace.length() > 0) {
77 const char* stack_trace_string = ToCString(stack_trace);
78 fprintf(stderr, "%s\n", stack_trace_string);
79 }
80 }
81 }
82
83 SkV8ExampleWindow::SkV8ExampleWindow(void* hwnd, JsCanvas* canvas)
84 : INHERITED(hwnd)
85 , fJsCanvas(canvas)
86 {
87 this->setConfig(SkBitmap::kARGB_8888_Config);
88 this->setVisibleP(true);
89 this->setClipToBounds(false);
90 }
91 46
92 JsCanvas* JsCanvas::Unwrap(Handle<Object> obj) { 47 JsCanvas* JsCanvas::Unwrap(Handle<Object> obj) {
93 Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0)); 48 Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
94 void* ptr = field->Value(); 49 void* ptr = field->Value();
95 return static_cast<JsCanvas*>(ptr); 50 return static_cast<JsCanvas*>(ptr);
96 } 51 }
97 52
98 void JsCanvas::Inval(const v8::FunctionCallbackInfo<Value>& args) {
99 Unwrap(args.This())->fWindow->inval(NULL);
100 }
101
102 void JsCanvas::FillRect(const v8::FunctionCallbackInfo<Value>& args) { 53 void JsCanvas::FillRect(const v8::FunctionCallbackInfo<Value>& args) {
103 JsCanvas* jsCanvas = Unwrap(args.This()); 54 JsCanvas* jsCanvas = Unwrap(args.This());
104 SkCanvas* canvas = jsCanvas->fCanvas; 55 SkCanvas* canvas = jsCanvas->fCanvas;
105 56
106 if (args.Length() != 4) { 57 if (args.Length() != 4) {
107 args.GetIsolate()->ThrowException( 58 args.GetIsolate()->ThrowException(
108 v8::String::NewFromUtf8( 59 v8::String::NewFromUtf8(
109 args.GetIsolate(), "Error: 4 arguments required.")); 60 args.GetIsolate(), "Error: 4 arguments required."));
110 return; 61 return;
111 } 62 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 } 108 }
158 109
159 long color = strtol(buf+1, NULL, 16); 110 long color = strtol(buf+1, NULL, 16);
160 jsCanvas->fFillStyle.setColor(SkColorSetA(SkColor(color), SK_AlphaOPAQUE)); 111 jsCanvas->fFillStyle.setColor(SkColorSetA(SkColor(color), SK_AlphaOPAQUE));
161 } 112 }
162 113
163 114
164 Persistent<ObjectTemplate> JsCanvas::fCanvasTemplate; 115 Persistent<ObjectTemplate> JsCanvas::fCanvasTemplate;
165 116
166 Handle<ObjectTemplate> JsCanvas::makeCanvasTemplate() { 117 Handle<ObjectTemplate> JsCanvas::makeCanvasTemplate() {
167 EscapableHandleScope handleScope(fIsolate); 118 EscapableHandleScope handleScope(fGlobal->getIsolate());
168 119
169 Local<ObjectTemplate> result = ObjectTemplate::New(); 120 Local<ObjectTemplate> result = ObjectTemplate::New();
170 121
171 // Add a field to store the pointer to a JsCanvas instance. 122 // Add a field to store the pointer to a JsCanvas instance.
172 result->SetInternalFieldCount(1); 123 result->SetInternalFieldCount(1);
173 124
174 // Add accessors for each of the fields of the canvas object. 125 // Add accessors for each of the fields of the canvas object.
175 result->SetAccessor( 126 result->SetAccessor(
176 String::NewFromUtf8(fIsolate, "fillStyle", String::kInternalizedString), 127 String::NewFromUtf8(
128 fGlobal->getIsolate(), "fillStyle", String::kInternalizedString),
177 GetFillStyle, SetFillStyle); 129 GetFillStyle, SetFillStyle);
178 130
179 // Add methods. 131 // Add methods.
180 result->Set( 132 result->Set(
181 String::NewFromUtf8( 133 String::NewFromUtf8(
182 fIsolate, "fillRect", String::kInternalizedString), 134 fGlobal->getIsolate(), "fillRect",
135 String::kInternalizedString),
183 FunctionTemplate::New(FillRect)); 136 FunctionTemplate::New(FillRect));
184 result->Set(
185 String::NewFromUtf8(
186 fIsolate, "inval", String::kInternalizedString),
187 FunctionTemplate::New(Inval));
188 137
189 // Return the result through the current handle scope. 138 // Return the result through the current handle scope.
190 return handleScope.Escape(result); 139 return handleScope.Escape(result);
191 } 140 }
192 141
193 142
194 // Wraps 'this' in a Javascript object. 143 // Wraps 'this' in a Javascript object.
195 Handle<Object> JsCanvas::wrap() { 144 Handle<Object> JsCanvas::wrap() {
196 // Handle scope for temporary handles. 145 // Handle scope for temporary handles.
197 EscapableHandleScope handleScope(fIsolate); 146 EscapableHandleScope handleScope(fGlobal->getIsolate());
198 147
199 // Fetch the template for creating JavaScript JsCanvas wrappers. 148 // Fetch the template for creating JavaScript JsCanvas wrappers.
200 // It only has to be created once, which we do on demand. 149 // It only has to be created once, which we do on demand.
201 if (fCanvasTemplate.IsEmpty()) { 150 if (fCanvasTemplate.IsEmpty()) {
202 Handle<ObjectTemplate> raw_template = this->makeCanvasTemplate(); 151 Handle<ObjectTemplate> raw_template = this->makeCanvasTemplate();
203 fCanvasTemplate.Reset(fIsolate, raw_template); 152 fCanvasTemplate.Reset(fGlobal->getIsolate(), raw_template);
204 } 153 }
205 Handle<ObjectTemplate> templ = 154 Handle<ObjectTemplate> templ =
206 Local<ObjectTemplate>::New(fIsolate, fCanvasTemplate); 155 Local<ObjectTemplate>::New(fGlobal->getIsolate(), fCanvasTemplate);
207 156
208 // Create an empty JsCanvas wrapper. 157 // Create an empty JsCanvas wrapper.
209 Local<Object> result = templ->NewInstance(); 158 Local<Object> result = templ->NewInstance();
210 159
211 // Wrap the raw C++ pointer in an External so it can be referenced 160 // Wrap the raw C++ pointer in an External so it can be referenced
212 // from within JavaScript. 161 // from within JavaScript.
213 Handle<External> canvasPtr = External::New(fIsolate, this); 162 Handle<External> canvasPtr = External::New(fGlobal->getIsolate(), this);
214 163
215 // Store the canvas pointer in the JavaScript wrapper. 164 // Store the canvas pointer in the JavaScript wrapper.
216 result->SetInternalField(0, canvasPtr); 165 result->SetInternalField(0, canvasPtr);
217 166
218 // Return the result through the current handle scope. Since each 167 // Return the result through the current handle scope. Since each
219 // of these handles will go away when the handle scope is deleted 168 // of these handles will go away when the handle scope is deleted
220 // we need to call Close to let one, the result, escape into the 169 // we need to call Close to let one, the result, escape into the
221 // outer handle scope. 170 // outer handle scope.
222 return handleScope.Escape(result); 171 return handleScope.Escape(result);
223 } 172 }
224 173
225 void JsCanvas::onDraw(SkCanvas* canvas, SkOSWindow* window) { 174 void JsCanvas::onDraw(SkCanvas* canvas) {
226 // Record canvas and window in this. 175 // Record canvas and window in this.
227 fCanvas = canvas; 176 fCanvas = canvas;
228 fWindow = window;
229 177
230 // Create a handle scope to keep the temporary object references. 178 // Create a handle scope to keep the temporary object references.
231 HandleScope handleScope(fIsolate); 179 HandleScope handleScope(fGlobal->getIsolate());
232 180
233 // Create a local context from our global context. 181 // Create a local context from our global context.
234 Local<Context> context = Local<Context>::New(fIsolate, fContext); 182 Local<Context> context = fGlobal->getContext();
235 183
236 // Enter the context so all the remaining operations take place there. 184 // Enter the context so all the remaining operations take place there.
237 Context::Scope contextScope(context); 185 Context::Scope contextScope(context);
238 186
239 // Wrap the C++ this pointer in a JavaScript wrapper. 187 // Wrap the C++ this pointer in a JavaScript wrapper.
240 Handle<Object> canvasObj = this->wrap(); 188 Handle<Object> canvasObj = this->wrap();
241 189
242 // Set up an exception handler before calling the Process function. 190 // Set up an exception handler before calling the Process function.
243 TryCatch tryCatch; 191 TryCatch tryCatch;
244 192
245 // Invoke the process function, giving the global object as 'this' 193 // Invoke the process function, giving the global object as 'this'
246 // and one argument, this JsCanvas. 194 // and one argument, this JsCanvas.
247 const int argc = 1; 195 const int argc = 1;
248 Handle<Value> argv[argc] = { canvasObj }; 196 Handle<Value> argv[argc] = { canvasObj };
249 Local<Function> onDraw = 197 Local<Function> onDraw =
250 Local<Function>::New(fIsolate, fOnDraw); 198 Local<Function>::New(fGlobal->getIsolate(), fOnDraw);
251 Handle<Value> result = onDraw->Call(context->Global(), argc, argv); 199 Handle<Value> result = onDraw->Call(context->Global(), argc, argv);
252 200
253 // Handle any exceptions or output. 201 // Handle any exceptions or output.
254 if (result.IsEmpty()) { 202 if (result.IsEmpty()) {
255 SkASSERT(tryCatch.HasCaught()); 203 SkASSERT(tryCatch.HasCaught());
256 // Print errors that happened during execution. 204 // Print errors that happened during execution.
257 reportException(fIsolate, &tryCatch); 205 fGlobal->reportException(&tryCatch);
258 } else { 206 } else {
259 SkASSERT(!tryCatch.HasCaught()); 207 SkASSERT(!tryCatch.HasCaught());
260 if (!result->IsUndefined()) { 208 if (!result->IsUndefined()) {
261 // If all went well and the result wasn't undefined then print 209 // If all went well and the result wasn't undefined then print
262 // the returned value. 210 // the returned value.
263 String::Utf8Value str(result); 211 String::Utf8Value str(result);
264 const char* cstr = ToCString(str); 212 const char* cstr = to_cstring(str);
265 printf("%s\n", cstr); 213 printf("%s\n", cstr);
266 } 214 }
267 } 215 }
268 } 216 }
269 217
270 void SkV8ExampleWindow::onDraw(SkCanvas* canvas) { 218 // Fetch the onDraw function from the global context.
271 219 bool JsCanvas::initialize() {
272 canvas->save();
273 canvas->drawColor(SK_ColorWHITE);
274
275 // Now jump into JS and call the onDraw(canvas) method defined there.
276 fJsCanvas->onDraw(canvas, this);
277
278 canvas->restore();
279
280 INHERITED::onDraw(canvas);
281 }
282
283
284 #ifdef SK_BUILD_FOR_WIN
285 void SkV8ExampleWindow::onHandleInval(const SkIRect& rect) {
286 RECT winRect;
287 winRect.top = rect.top();
288 winRect.bottom = rect.bottom();
289 winRect.right = rect.right();
290 winRect.left = rect.left();
291 InvalidateRect((HWND)this->getHWND(), &winRect, false);
292 }
293 #endif
294
295
296 // The callback that is invoked by v8 whenever the JavaScript 'print'
297 // function is called. Prints its arguments on stdout separated by
298 // spaces and ending with a newline.
299 void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
300 bool first = true;
301 HandleScope handle_scope(args.GetIsolate());
302 for (int i = 0; i < args.Length(); i++) {
303 if (first) {
304 first = false;
305 } else {
306 printf(" ");
307 }
308 v8::String::Utf8Value str(args[i]);
309 printf("%s", ToCString(str));
310 }
311 printf("\n");
312 fflush(stdout);
313 }
314
315
316 // Creates a new execution environment containing the built-in
317 // function draw().
318 Handle<Context> createRootContext(Isolate* isolate) {
319 // Create a template for the global object.
320 Handle<ObjectTemplate> global = ObjectTemplate::New();
321
322 // This is where we would inject any globals into the root Context
323 // using global->Set(...)
324
325 global->Set(v8::String::NewFromUtf8(isolate, "print"),
326 v8::FunctionTemplate::New(Print));
327
328 return Context::New(isolate, NULL, global);
329 }
330
331
332 // Parse and run script. Then fetch out the onDraw function from the global
333 // object.
334 bool JsCanvas::initialize(const char script[]) {
335 220
336 // Create a stack-allocated handle scope. 221 // Create a stack-allocated handle scope.
337 HandleScope handleScope(fIsolate); 222 HandleScope handleScope(fGlobal->getIsolate());
338 223
339 printf("Before create context\n"); 224 // Create a local context from our global context.
340 225 Local<Context> context = fGlobal->getContext();
341 // Create a new context.
342 Handle<Context> context = createRootContext(fIsolate);
343 226
344 // Enter the scope so all operations take place in the scope. 227 // Enter the scope so all operations take place in the scope.
345 Context::Scope contextScope(context); 228 Context::Scope contextScope(context);
346 229
347 v8::TryCatch try_catch; 230 v8::TryCatch try_catch;
348 231
349 // Compile the source code. 232 Handle<String> fn_name = String::NewFromUtf8(
350 Handle<String> source = String::NewFromUtf8(fIsolate, script); 233 fGlobal->getIsolate(), "onDraw");
351 printf("Before Compile\n");
352 Handle<Script> compiled_script = Script::Compile(source);
353 printf("After Compile\n");
354
355 if (compiled_script.IsEmpty()) {
356 // Print errors that happened during compilation.
357 reportException(fIsolate, &try_catch);
358 return false;
359 }
360 printf("After Exception.\n");
361
362 // Try running it now to create the onDraw function.
363 Handle<Value> result = compiled_script->Run();
364
365 // Handle any exceptions or output.
366 if (result.IsEmpty()) {
367 SkASSERT(try_catch.HasCaught());
368 // Print errors that happened during execution.
369 reportException(fIsolate, &try_catch);
370 return false;
371 } else {
372 SkASSERT(!try_catch.HasCaught());
373 if (!result->IsUndefined()) {
374 // If all went well and the result wasn't undefined then print
375 // the returned value.
376 String::Utf8Value str(result);
377 const char* cstr = ToCString(str);
378 printf("%s\n", cstr);
379 return false;
380 }
381 }
382
383 Handle<String> fn_name = String::NewFromUtf8(fIsolate, "onDraw");
384 Handle<Value> fn_val = context->Global()->Get(fn_name); 234 Handle<Value> fn_val = context->Global()->Get(fn_name);
385 235
386 if (!fn_val->IsFunction()) { 236 if (!fn_val->IsFunction()) {
387 printf("Not a function.\n"); 237 printf("Not a function.\n");
388 return false; 238 return false;
389 } 239 }
390 240
391 // It is a function; cast it to a Function. 241 // It is a function; cast it to a Function.
392 Handle<Function> fn_fun = Handle<Function>::Cast(fn_val); 242 Handle<Function> fn_fun = Handle<Function>::Cast(fn_val);
393 243
394 // Store the function in a Persistent handle, since we also want that to 244 // Store the function in a Persistent handle, since we also want that to
395 // remain after this call returns. 245 // remain after this call returns.
396 fOnDraw.Reset(fIsolate, fn_fun); 246 fOnDraw.Reset(fGlobal->getIsolate(), fn_fun);
397 247
398 // Also make the context persistent.
399 fContext.Reset(fIsolate, context);
400 return true; 248 return true;
401 } 249 }
402 250
251
252 SkV8ExampleWindow::SkV8ExampleWindow(void* hwnd, JsCanvas* canvas)
253 : INHERITED(hwnd)
254 , fJsCanvas(canvas)
255 {
256 this->setConfig(SkBitmap::kARGB_8888_Config);
257 this->setVisibleP(true);
258 this->setClipToBounds(false);
259 }
260
261 void SkV8ExampleWindow::onDraw(SkCanvas* canvas) {
262
263 canvas->save();
264 canvas->drawColor(SK_ColorWHITE);
265
266 // Now jump into JS and call the onDraw(canvas) method defined there.
267 fJsCanvas->onDraw(canvas);
268
269 canvas->restore();
270
271 INHERITED::onDraw(canvas);
272 }
273
274
275 #ifdef SK_BUILD_FOR_WIN
276 void SkV8ExampleWindow::onHandleInval(const SkIRect& rect) {
277 RECT winRect;
278 winRect.top = rect.top();
279 winRect.bottom = rect.bottom();
280 winRect.right = rect.right();
281 winRect.left = rect.left();
282 InvalidateRect((HWND)this->getHWND(), &winRect, false);
283 }
284 #endif
285
403 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 286 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
404 printf("Started\n"); 287 printf("Started\n");
405 288
406 SkCommandLineFlags::Parse(argc, argv); 289 SkCommandLineFlags::Parse(argc, argv);
407 290
408 // Get the default Isolate created at startup. 291 // Get the default Isolate created at startup.
409 Isolate* isolate = Isolate::GetCurrent(); 292 Isolate* isolate = Isolate::GetCurrent();
410 293 Global* global = new Global(isolate);
411 JsCanvas* jsCanvas = new JsCanvas(isolate);
412 294
413 const char* script = 295 const char* script =
414 "function onDraw(canvas) { \n" 296 "function onDraw(canvas) { \n"
415 " canvas.fillStyle = '#00FF00'; \n" 297 " canvas.fillStyle = '#00FF00'; \n"
416 " canvas.fillRect(20, 20, 100, 100); \n" 298 " canvas.fillRect(20, 20, 100, 100); \n"
417 " canvas.inval(); \n" 299 " canvas.inval(); \n"
418 "} \n"; 300 "} \n";
419 301
420 SkAutoTUnref<SkData> data; 302 SkAutoTUnref<SkData> data;
421 if (FLAGS_infile.count()) { 303 if (FLAGS_infile.count()) {
422 data.reset(SkData::NewFromFileName(FLAGS_infile[0])); 304 data.reset(SkData::NewFromFileName(FLAGS_infile[0]));
423 script = static_cast<const char*>(data->data()); 305 script = static_cast<const char*>(data->data());
424 } 306 }
425 if (NULL == script) { 307 if (NULL == script) {
426 printf("Could not load file: %s.\n", FLAGS_infile[0]); 308 printf("Could not load file: %s.\n", FLAGS_infile[0]);
427 exit(1); 309 exit(1);
428 } 310 }
429 if (!jsCanvas->initialize(script)) { 311
312 if (!global->parseScript(script)) {
313 exit(1);
314 }
315
316 JsCanvas* jsCanvas = new JsCanvas(global);
317
318 if (!jsCanvas->initialize()) {
430 printf("Failed to initialize.\n"); 319 printf("Failed to initialize.\n");
431 exit(1); 320 exit(1);
432 } 321 }
433 return new SkV8ExampleWindow(hwnd, jsCanvas); 322 SkV8ExampleWindow* win = new SkV8ExampleWindow(hwnd, jsCanvas);
323 global->setWindow(win);
324 return win;
434 } 325 }
OLDNEW
« no previous file with comments | « experimental/SkV8Example/SkV8Example.h ('k') | experimental/SkV8Example/sample.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698