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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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