• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  *
8  */
9 #include <v8.h>
10 
11 using namespace v8;
12 
13 #include "Global.h"
14 #include "BaseContext.h"
15 #include "Path2D.h"
16 #include "SkCanvas.h"
17 
18 
Unwrap(Handle<Object> obj)19 BaseContext* BaseContext::Unwrap(Handle<Object> obj) {
20     Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
21     void* ptr = field->Value();
22     return static_cast<BaseContext*>(ptr);
23 }
24 
FillRect(const v8::FunctionCallbackInfo<Value> & args)25 void BaseContext::FillRect(const v8::FunctionCallbackInfo<Value>& args) {
26     BaseContext* BaseContext = Unwrap(args.This());
27     SkCanvas* canvas = BaseContext->getCanvas();
28     if (NULL == canvas) {
29         return;
30     }
31 
32     if (args.Length() != 4) {
33         args.GetIsolate()->ThrowException(
34                 v8::String::NewFromUtf8(
35                         args.GetIsolate(), "Error: 4 arguments required."));
36         return;
37     }
38     double x = args[0]->NumberValue();
39     double y = args[1]->NumberValue();
40     double w = args[2]->NumberValue();
41     double h = args[3]->NumberValue();
42 
43     SkRect rect = {
44         SkDoubleToScalar(x),
45         SkDoubleToScalar(y),
46         SkDoubleToScalar(x) + SkDoubleToScalar(w),
47         SkDoubleToScalar(y) + SkDoubleToScalar(h)
48     };
49     canvas->drawRect(rect, BaseContext->fFillStyle);
50 }
51 
Save(const v8::FunctionCallbackInfo<Value> & args)52 void BaseContext::Save(const v8::FunctionCallbackInfo<Value>& args) {
53     BaseContext* BaseContext = Unwrap(args.This());
54     SkCanvas* canvas = BaseContext->getCanvas();
55     if (NULL == canvas) {
56         return;
57     }
58 
59     canvas->save();
60 }
61 
Restore(const v8::FunctionCallbackInfo<Value> & args)62 void BaseContext::Restore(const v8::FunctionCallbackInfo<Value>& args) {
63     BaseContext* BaseContext = Unwrap(args.This());
64     SkCanvas* canvas = BaseContext->getCanvas();
65     if (NULL == canvas) {
66         return;
67     }
68 
69     canvas->restore();
70 }
71 
Rotate(const v8::FunctionCallbackInfo<Value> & args)72 void BaseContext::Rotate(const v8::FunctionCallbackInfo<Value>& args) {
73     BaseContext* BaseContext = Unwrap(args.This());
74     SkCanvas* canvas = BaseContext->getCanvas();
75     if (NULL == canvas) {
76         return;
77     }
78 
79     if (args.Length() != 1) {
80         args.GetIsolate()->ThrowException(
81                 v8::String::NewFromUtf8(
82                         args.GetIsolate(), "Error: 1 arguments required."));
83         return;
84     }
85     double angle = args[0]->NumberValue();
86     canvas->rotate(SkRadiansToDegrees(angle));
87 }
88 
Translate(const v8::FunctionCallbackInfo<Value> & args)89 void BaseContext::Translate(const v8::FunctionCallbackInfo<Value>& args) {
90     BaseContext* BaseContext = Unwrap(args.This());
91     SkCanvas* canvas = BaseContext->getCanvas();
92     if (NULL == canvas) {
93         return;
94     }
95 
96     if (args.Length() != 2) {
97         args.GetIsolate()->ThrowException(
98                 v8::String::NewFromUtf8(
99                         args.GetIsolate(), "Error: 2 arguments required."));
100         return;
101     }
102     double dx = args[0]->NumberValue();
103     double dy = args[1]->NumberValue();
104     canvas->translate(SkDoubleToScalar(dx), SkDoubleToScalar(dy));
105 }
106 
ResetTransform(const v8::FunctionCallbackInfo<Value> & args)107 void BaseContext::ResetTransform(const v8::FunctionCallbackInfo<Value>& args) {
108     BaseContext* BaseContext = Unwrap(args.This());
109     SkCanvas* canvas = BaseContext->getCanvas();
110     if (NULL == canvas) {
111         return;
112     }
113 
114     canvas->resetMatrix();
115 }
116 
Stroke(const v8::FunctionCallbackInfo<Value> & args)117 void BaseContext::Stroke(const v8::FunctionCallbackInfo<Value>& args) {
118     BaseContext* BaseContext = Unwrap(args.This());
119     SkCanvas* canvas = BaseContext->getCanvas();
120     if (NULL == canvas) {
121         return;
122     }
123 
124     if (args.Length() != 1) {
125         args.GetIsolate()->ThrowException(
126                 v8::String::NewFromUtf8(
127                         args.GetIsolate(), "Error: 1 arguments required."));
128         return;
129     }
130 
131     Handle<External> field = Handle<External>::Cast(
132             args[0]->ToObject()->GetInternalField(0));
133     void* ptr = field->Value();
134     Path2D* path = static_cast<Path2D*>(ptr);
135 
136     canvas->drawPath(path->getSkPath(), BaseContext->fStrokeStyle);
137 }
138 
Fill(const v8::FunctionCallbackInfo<Value> & args)139 void BaseContext::Fill(const v8::FunctionCallbackInfo<Value>& args) {
140     BaseContext* BaseContext = Unwrap(args.This());
141     SkCanvas* canvas = BaseContext->getCanvas();
142     if (NULL == canvas) {
143         return;
144     }
145 
146     if (args.Length() != 1) {
147         args.GetIsolate()->ThrowException(
148                 v8::String::NewFromUtf8(
149                         args.GetIsolate(), "Error: 1 arguments required."));
150         return;
151     }
152 
153     Handle<External> field = Handle<External>::Cast(
154             args[0]->ToObject()->GetInternalField(0));
155     void* ptr = field->Value();
156     Path2D* path = static_cast<Path2D*>(ptr);
157 
158     canvas->drawPath(path->getSkPath(), BaseContext->fFillStyle);
159 }
160 
GetStyle(Local<String> name,const PropertyCallbackInfo<Value> & info,const SkPaint & style)161 void BaseContext::GetStyle(Local<String> name,
162                          const PropertyCallbackInfo<Value>& info,
163                          const SkPaint& style) {
164     char buf[8];
165     SkColor color = style.getColor();
166     sprintf(buf, "#%02X%02X%02X", SkColorGetR(color), SkColorGetG(color),
167             SkColorGetB(color));
168 
169     info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buf));
170 }
171 
SetStyle(Local<String> name,Local<Value> value,const PropertyCallbackInfo<void> & info,SkPaint & style)172 void BaseContext::SetStyle(Local<String> name, Local<Value> value,
173                          const PropertyCallbackInfo<void>& info,
174                          SkPaint& style) {
175     Local<String> s = value->ToString();
176     if (s->Length() != 7 && s->Length() != 9) {
177         info.GetIsolate()->ThrowException(
178                 v8::String::NewFromUtf8(
179                         info.GetIsolate(),
180                         "Invalid fill style format length."));
181         return;
182     }
183     char buf[10];
184     s->WriteUtf8(buf, sizeof(buf));
185 
186     if (buf[0] != '#') {
187         info.GetIsolate()->ThrowException(
188                 v8::String::NewFromUtf8(
189                         info.GetIsolate(), "Invalid fill style format."));
190         return;
191     }
192 
193     // Colors can be RRGGBBAA, but SkColor uses ARGB.
194     long color = strtol(buf+1, NULL, 16);
195     uint32_t alpha = SK_AlphaOPAQUE;
196     if (s->Length() == 9) {
197         alpha = color & 0xFF;
198         color >>= 8;
199     }
200     style.setColor(SkColorSetA(SkColor(color), alpha));
201 }
202 
GetFillStyle(Local<String> name,const PropertyCallbackInfo<Value> & info)203 void BaseContext::GetFillStyle(Local<String> name,
204                              const PropertyCallbackInfo<Value>& info) {
205     BaseContext* baseContext = Unwrap(info.This());
206     GetStyle(name, info, baseContext->fFillStyle);
207 }
208 
GetStrokeStyle(Local<String> name,const PropertyCallbackInfo<Value> & info)209 void BaseContext::GetStrokeStyle(Local<String> name,
210                                const PropertyCallbackInfo<Value>& info) {
211     BaseContext* baseContext = Unwrap(info.This());
212     GetStyle(name, info, baseContext->fStrokeStyle);
213 }
214 
SetFillStyle(Local<String> name,Local<Value> value,const PropertyCallbackInfo<void> & info)215 void BaseContext::SetFillStyle(Local<String> name, Local<Value> value,
216                             const PropertyCallbackInfo<void>& info) {
217     BaseContext* baseContext = Unwrap(info.This());
218     SetStyle(name, value, info, baseContext->fFillStyle);
219 }
220 
SetStrokeStyle(Local<String> name,Local<Value> value,const PropertyCallbackInfo<void> & info)221 void BaseContext::SetStrokeStyle(Local<String> name, Local<Value> value,
222                                const PropertyCallbackInfo<void>& info) {
223     BaseContext* baseContext = Unwrap(info.This());
224     SetStyle(name, value, info, baseContext->fStrokeStyle);
225 }
226 
227 
GetWidth(Local<String> name,const PropertyCallbackInfo<Value> & info)228 void BaseContext::GetWidth(Local<String> name,
229                          const PropertyCallbackInfo<Value>& info) {
230     BaseContext* baseContext = Unwrap(info.This());
231     SkCanvas* canvas = baseContext->getCanvas();
232     if (NULL == canvas) {
233         return;
234     }
235     SkISize size = canvas->getDeviceSize();
236 
237     info.GetReturnValue().Set(
238             Int32::New(baseContext->fGlobal->getIsolate(), size.fWidth));
239 }
240 
GetHeight(Local<String> name,const PropertyCallbackInfo<Value> & info)241 void BaseContext::GetHeight(Local<String> name,
242                          const PropertyCallbackInfo<Value>& info) {
243     BaseContext* baseContext = Unwrap(info.This());
244     SkCanvas* canvas = baseContext->getCanvas();
245     if (NULL == canvas) {
246         return;
247     }
248     SkISize size = canvas->getDeviceSize();
249 
250     info.GetReturnValue().Set(
251             Int32::New(baseContext->fGlobal->getIsolate(), size.fHeight));
252 }
253 
254 #define ADD_METHOD(name, fn) \
255     tmpl->Set(String::NewFromUtf8( \
256          fGlobal->getIsolate(), name, \
257          String::kInternalizedString), \
258              FunctionTemplate::New(fGlobal->getIsolate(), fn))
259 
addAttributesAndMethods(Handle<ObjectTemplate> tmpl)260 void BaseContext::addAttributesAndMethods(Handle<ObjectTemplate> tmpl) {
261     HandleScope scope(fGlobal->getIsolate());
262 
263     // Add accessors for each of the fields of the context object.
264     tmpl->SetAccessor(String::NewFromUtf8(
265         fGlobal->getIsolate(), "fillStyle", String::kInternalizedString),
266             GetFillStyle, SetFillStyle);
267     tmpl->SetAccessor(String::NewFromUtf8(
268         fGlobal->getIsolate(), "strokeStyle", String::kInternalizedString),
269             GetStrokeStyle, SetStrokeStyle);
270     tmpl->SetAccessor(String::NewFromUtf8(
271         fGlobal->getIsolate(), "width", String::kInternalizedString),
272             GetWidth);
273     tmpl->SetAccessor(String::NewFromUtf8(
274         fGlobal->getIsolate(), "height", String::kInternalizedString),
275             GetHeight);
276 
277     // Add methods.
278     ADD_METHOD("fillRect", FillRect);
279     ADD_METHOD("stroke", Stroke);
280     ADD_METHOD("fill", Fill);
281     ADD_METHOD("rotate", Rotate);
282     ADD_METHOD("save", Save);
283     ADD_METHOD("restore", Restore);
284     ADD_METHOD("translate", Translate);
285     ADD_METHOD("resetTransform", ResetTransform);
286 }
287