Home | History | Annotate | Download | only in SkV8Example
      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