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

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

Issue 186783004: Factor out a BaseContext from JsContext. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Review comments. Created 6 years, 9 months 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/JsContext.h ('k') | gyp/v8.gyp » ('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 /* 2 /*
3 * Copyright 2013 Google Inc. 3 * Copyright 2013 Google Inc.
4 * 4 *
5 * 5 *
6 * Use of this source code is governed by a BSD-style license that can be 6 * Use of this source code is governed by a BSD-style license that can be
7 * found in the LICENSE file. 7 * found in the LICENSE file.
8 * 8 *
9 */ 9 */
10 #include <v8.h> 10 #include <v8.h>
11 11
12 using namespace v8; 12 using namespace v8;
13 13
14 #include "Global.h" 14 #include "Global.h"
15 #include "JsContext.h" 15 #include "JsContext.h"
16 #include "Path2D.h" 16 #include "Path2D.h"
17 #include "SkCanvas.h" 17 #include "SkCanvas.h"
18 18
19 19
20 // Extracts a C string from a V8 Utf8Value. 20 // Extracts a C string from a V8 Utf8Value.
21 // TODO(jcgregrio) Currently dup'd in two files, fix. 21 // TODO(jcgregrio) Currently dup'd in two files, fix.
22 static const char* to_cstring(const v8::String::Utf8Value& value) { 22 static const char* to_cstring(const v8::String::Utf8Value& value) {
23 return *value ? *value : "<string conversion failed>"; 23 return *value ? *value : "<string conversion failed>";
24 } 24 }
25 25
26 JsContext* JsContext::Unwrap(Handle<Object> obj) {
27 Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
28 void* ptr = field->Value();
29 return static_cast<JsContext*>(ptr);
30 }
31
32 void JsContext::FillRect(const v8::FunctionCallbackInfo<Value>& args) {
33 JsContext* jsContext = Unwrap(args.This());
34 SkCanvas* canvas = jsContext->fCanvas;
35
36 if (args.Length() != 4) {
37 args.GetIsolate()->ThrowException(
38 v8::String::NewFromUtf8(
39 args.GetIsolate(), "Error: 4 arguments required."));
40 return;
41 }
42 // TODO(jcgregorio) Really figure out the conversion from JS numbers to
43 // SkScalars. Maybe test if int first? Not sure of the performance impact.
44 double x = args[0]->NumberValue();
45 double y = args[1]->NumberValue();
46 double w = args[2]->NumberValue();
47 double h = args[3]->NumberValue();
48
49 SkRect rect = {
50 SkDoubleToScalar(x),
51 SkDoubleToScalar(y),
52 SkDoubleToScalar(x) + SkDoubleToScalar(w),
53 SkDoubleToScalar(y) + SkDoubleToScalar(h)
54 };
55 canvas->drawRect(rect, jsContext->fFillStyle);
56 }
57
58 void JsContext::Save(const v8::FunctionCallbackInfo<Value>& args) {
59 JsContext* jsContext = Unwrap(args.This());
60 SkCanvas* canvas = jsContext->fCanvas;
61
62 canvas->save();
63 }
64
65 void JsContext::Restore(const v8::FunctionCallbackInfo<Value>& args) {
66 JsContext* jsContext = Unwrap(args.This());
67 SkCanvas* canvas = jsContext->fCanvas;
68
69 canvas->restore();
70 }
71
72 void JsContext::Rotate(const v8::FunctionCallbackInfo<Value>& args) {
73 JsContext* jsContext = Unwrap(args.This());
74 SkCanvas* canvas = jsContext->fCanvas;
75
76 if (args.Length() != 1) {
77 args.GetIsolate()->ThrowException(
78 v8::String::NewFromUtf8(
79 args.GetIsolate(), "Error: 1 arguments required."));
80 return;
81 }
82 double angle = args[0]->NumberValue();
83 canvas->rotate(SkRadiansToDegrees(angle));
84 }
85
86 void JsContext::Translate(const v8::FunctionCallbackInfo<Value>& args) {
87 JsContext* jsContext = Unwrap(args.This());
88 SkCanvas* canvas = jsContext->fCanvas;
89
90 if (args.Length() != 2) {
91 args.GetIsolate()->ThrowException(
92 v8::String::NewFromUtf8(
93 args.GetIsolate(), "Error: 2 arguments required."));
94 return;
95 }
96 double dx = args[0]->NumberValue();
97 double dy = args[1]->NumberValue();
98 canvas->translate(SkDoubleToScalar(dx), SkDoubleToScalar(dy));
99 }
100
101 void JsContext::ResetTransform(const v8::FunctionCallbackInfo<Value>& args) {
102 JsContext* jsContext = Unwrap(args.This());
103 SkCanvas* canvas = jsContext->fCanvas;
104
105 canvas->resetMatrix();
106 }
107
108 void JsContext::Stroke(const v8::FunctionCallbackInfo<Value>& args) {
109 JsContext* jsContext = Unwrap(args.This());
110 SkCanvas* canvas = jsContext->fCanvas;
111
112 if (args.Length() != 1) {
113 args.GetIsolate()->ThrowException(
114 v8::String::NewFromUtf8(
115 args.GetIsolate(), "Error: 1 arguments required."));
116 return;
117 }
118
119 Handle<External> field = Handle<External>::Cast(
120 args[0]->ToObject()->GetInternalField(0));
121 void* ptr = field->Value();
122 Path2D* path = static_cast<Path2D*>(ptr);
123
124 canvas->drawPath(path->getSkPath(), jsContext->fStrokeStyle);
125 }
126
127 void JsContext::Fill(const v8::FunctionCallbackInfo<Value>& args) {
128 JsContext* jsContext = Unwrap(args.This());
129 SkCanvas* canvas = jsContext->fCanvas;
130
131 if (args.Length() != 1) {
132 args.GetIsolate()->ThrowException(
133 v8::String::NewFromUtf8(
134 args.GetIsolate(), "Error: 1 arguments required."));
135 return;
136 }
137
138 Handle<External> field = Handle<External>::Cast(
139 args[0]->ToObject()->GetInternalField(0));
140 void* ptr = field->Value();
141 Path2D* path = static_cast<Path2D*>(ptr);
142
143 canvas->drawPath(path->getSkPath(), jsContext->fFillStyle);
144 }
145
146 void JsContext::GetStyle(Local<String> name,
147 const PropertyCallbackInfo<Value>& info,
148 const SkPaint& style) {
149 char buf[8];
150 SkColor color = style.getColor();
151 sprintf(buf, "#%02X%02X%02X", SkColorGetR(color), SkColorGetG(color),
152 SkColorGetB(color));
153
154 info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buf));
155 }
156
157 void JsContext::SetStyle(Local<String> name, Local<Value> value,
158 const PropertyCallbackInfo<void>& info,
159 SkPaint& style) {
160 Local<String> s = value->ToString();
161 if (s->Length() != 7 && s->Length() != 9) {
162 info.GetIsolate()->ThrowException(
163 v8::String::NewFromUtf8(
164 info.GetIsolate(),
165 "Invalid fill style format length."));
166 return;
167 }
168 char buf[10];
169 s->WriteUtf8(buf, sizeof(buf));
170
171 if (buf[0] != '#') {
172 info.GetIsolate()->ThrowException(
173 v8::String::NewFromUtf8(
174 info.GetIsolate(), "Invalid fill style format."));
175 return;
176 }
177
178 // Colors can be RRGGBBAA, but SkColor uses ARGB.
179 long color = strtol(buf+1, NULL, 16);
180 uint32_t alpha = SK_AlphaOPAQUE;
181 if (s->Length() == 9) {
182 alpha = color & 0xFF;
183 color >>= 8;
184 }
185 style.setColor(SkColorSetA(SkColor(color), alpha));
186 }
187
188 void JsContext::GetFillStyle(Local<String> name,
189 const PropertyCallbackInfo<Value>& info) {
190 JsContext* jsContext = Unwrap(info.This());
191 GetStyle(name, info, jsContext->fFillStyle);
192 }
193
194 void JsContext::GetStrokeStyle(Local<String> name,
195 const PropertyCallbackInfo<Value>& info) {
196 JsContext* jsContext = Unwrap(info.This());
197 GetStyle(name, info, jsContext->fStrokeStyle);
198 }
199
200 void JsContext::SetFillStyle(Local<String> name, Local<Value> value,
201 const PropertyCallbackInfo<void>& info) {
202 JsContext* jsContext = Unwrap(info.This());
203 SetStyle(name, value, info, jsContext->fFillStyle);
204 }
205
206 void JsContext::SetStrokeStyle(Local<String> name, Local<Value> value,
207 const PropertyCallbackInfo<void>& info) {
208 JsContext* jsContext = Unwrap(info.This());
209 SetStyle(name, value, info, jsContext->fStrokeStyle);
210 }
211
212
213 void JsContext::GetWidth(Local<String> name,
214 const PropertyCallbackInfo<Value>& info) {
215 JsContext* jsContext = Unwrap(info.This());
216 SkISize size = jsContext->fCanvas->getDeviceSize();
217
218 info.GetReturnValue().Set(
219 Int32::New(jsContext->fGlobal->getIsolate(), size.fWidth));
220 }
221
222 void JsContext::GetHeight(Local<String> name,
223 const PropertyCallbackInfo<Value>& info) {
224 JsContext* jsContext = Unwrap(info.This());
225 SkISize size = jsContext->fCanvas->getDeviceSize();
226
227 info.GetReturnValue().Set(
228 Int32::New(jsContext->fGlobal->getIsolate(), size.fHeight));
229 }
230
231
232 Persistent<ObjectTemplate> JsContext::gContextTemplate; 26 Persistent<ObjectTemplate> JsContext::gContextTemplate;
233 27
234 #define ADD_METHOD(name, fn) \
235 result->Set(String::NewFromUtf8( \
236 fGlobal->getIsolate(), name, \
237 String::kInternalizedString), \
238 FunctionTemplate::New(fGlobal->getIsolate(), fn))
239
240 Handle<ObjectTemplate> JsContext::makeContextTemplate() {
241 EscapableHandleScope handleScope(fGlobal->getIsolate());
242
243 Local<ObjectTemplate> result = ObjectTemplate::New();
244
245 // Add a field to store the pointer to a JsContext instance.
246 result->SetInternalFieldCount(1);
247
248 // Add accessors for each of the fields of the context object.
249 result->SetAccessor(String::NewFromUtf8(
250 fGlobal->getIsolate(), "fillStyle", String::kInternalizedString),
251 GetFillStyle, SetFillStyle);
252 result->SetAccessor(String::NewFromUtf8(
253 fGlobal->getIsolate(), "strokeStyle", String::kInternalizedString),
254 GetStrokeStyle, SetStrokeStyle);
255 result->SetAccessor(String::NewFromUtf8(
256 fGlobal->getIsolate(), "width", String::kInternalizedString),
257 GetWidth);
258 result->SetAccessor(String::NewFromUtf8(
259 fGlobal->getIsolate(), "height", String::kInternalizedString),
260 GetHeight);
261
262 // Add methods.
263 ADD_METHOD("fillRect", FillRect);
264 ADD_METHOD("stroke", Stroke);
265 ADD_METHOD("fill", Fill);
266 ADD_METHOD("rotate", Rotate);
267 ADD_METHOD("save", Save);
268 ADD_METHOD("restore", Restore);
269 ADD_METHOD("translate", Translate);
270 ADD_METHOD("resetTransform", ResetTransform);
271
272 // Return the result through the current handle scope.
273 return handleScope.Escape(result);
274 }
275
276
277 // Wraps 'this' in a Javascript object. 28 // Wraps 'this' in a Javascript object.
278 Handle<Object> JsContext::wrap() { 29 Handle<Object> JsContext::wrap() {
279 // Handle scope for temporary handles. 30 // Handle scope for temporary handles.
280 EscapableHandleScope handleScope(fGlobal->getIsolate()); 31 EscapableHandleScope handleScope(fGlobal->getIsolate());
281 32
282 // Fetch the template for creating JavaScript JsContext wrappers. 33 // Fetch the template for creating JavaScript JsContext wrappers.
283 // It only has to be created once, which we do on demand. 34 // It only has to be created once, which we do on demand.
284 if (gContextTemplate.IsEmpty()) { 35 if (gContextTemplate.IsEmpty()) {
285 Handle<ObjectTemplate> raw_template = this->makeContextTemplate(); 36 Local<ObjectTemplate> localTemplate = ObjectTemplate::New();
286 gContextTemplate.Reset(fGlobal->getIsolate(), raw_template); 37
38 // Add a field to store the pointer to a JsContext instance.
39 localTemplate->SetInternalFieldCount(1);
40
41 this->addAttributesAndMethods(localTemplate);
42
43 gContextTemplate.Reset(fGlobal->getIsolate(), localTemplate);
287 } 44 }
288 Handle<ObjectTemplate> templ = 45 Handle<ObjectTemplate> templ =
289 Local<ObjectTemplate>::New(fGlobal->getIsolate(), gContextTemplate); 46 Local<ObjectTemplate>::New(fGlobal->getIsolate(), gContextTemplate);
290 47
291 // Create an empty JsContext wrapper. 48 // Create an empty JsContext wrapper.
292 Local<Object> result = templ->NewInstance(); 49 Local<Object> result = templ->NewInstance();
293 50
294 // Wrap the raw C++ pointer in an External so it can be referenced 51 // Wrap the raw C++ pointer in an External so it can be referenced
295 // from within JavaScript. 52 // from within JavaScript.
296 Handle<External> contextPtr = External::New(fGlobal->getIsolate(), this); 53 Handle<External> contextPtr = External::New(fGlobal->getIsolate(), this);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 131
375 // It is a function; cast it to a Function. 132 // It is a function; cast it to a Function.
376 Handle<Function> fn_fun = Handle<Function>::Cast(fn_val); 133 Handle<Function> fn_fun = Handle<Function>::Cast(fn_val);
377 134
378 // Store the function in a Persistent handle, since we also want that to 135 // Store the function in a Persistent handle, since we also want that to
379 // remain after this call returns. 136 // remain after this call returns.
380 fOnDraw.Reset(fGlobal->getIsolate(), fn_fun); 137 fOnDraw.Reset(fGlobal->getIsolate(), fn_fun);
381 138
382 return true; 139 return true;
383 } 140 }
OLDNEW
« no previous file with comments | « experimental/SkV8Example/JsContext.h ('k') | gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698