Index: experimental/SkV8Example/Path2D.cpp |
diff --git a/experimental/SkV8Example/Path2D.cpp b/experimental/SkV8Example/Path2D.cpp |
index 5956f69de3ade6e6fea477cb364cbe34220e4371..dded6881671fa5915e52d7c8d0b0cc7cff52f7bf 100644 |
--- a/experimental/SkV8Example/Path2D.cpp |
+++ b/experimental/SkV8Example/Path2D.cpp |
@@ -11,234 +11,45 @@ |
#include "Global.h" |
Global* Path2D::gGlobal = NULL; |
+v8::Persistent<v8::ObjectTemplate> Path2D::gPath2DTemplate; |
-void Path2D::ConstructPath(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- v8::HandleScope handleScope(gGlobal->getIsolate()); |
- Path2D* path = new Path2D(); |
- args.This()->SetInternalField( |
- 0, v8::External::New(gGlobal->getIsolate(), path)); |
+void weakPath2DCallback(const v8::WeakCallbackData<v8::Object, Path2D>& args) { |
+ delete args.GetParameter(); |
} |
-#define ADD_METHOD(name, fn) \ |
- constructor->InstanceTemplate()->Set( \ |
- v8::String::NewFromUtf8( \ |
- global->getIsolate(), name, \ |
- v8::String::kInternalizedString), \ |
- v8::FunctionTemplate::New(global->getIsolate(), fn)) |
- |
-// Install the constructor in the global scope so Path2Ds can be constructed |
-// in JS. |
-void Path2D::AddToGlobal(Global* global) { |
- gGlobal = global; |
- |
- // Create a stack-allocated handle scope. |
+// Wraps an SkPath* in a Path2D object. |
+Path2D::Path2D(SkPath* path) : path_(path) { |
+ // Handle scope for temporary handles. |
v8::HandleScope handleScope(gGlobal->getIsolate()); |
- v8::Handle<v8::Context> context = gGlobal->getContext(); |
- |
- // Enter the scope so all operations take place in the scope. |
- v8::Context::Scope contextScope(context); |
- |
- v8::Local<v8::FunctionTemplate> constructor = v8::FunctionTemplate::New( |
- gGlobal->getIsolate(), Path2D::ConstructPath); |
- constructor->InstanceTemplate()->SetInternalFieldCount(1); |
- |
- ADD_METHOD("closePath", ClosePath); |
- ADD_METHOD("moveTo", MoveTo); |
- ADD_METHOD("lineTo", LineTo); |
- ADD_METHOD("quadraticCurveTo", QuadraticCurveTo); |
- ADD_METHOD("bezierCurveTo", BezierCurveTo); |
- ADD_METHOD("arc", Arc); |
- ADD_METHOD("rect", Rect); |
- ADD_METHOD("oval", Oval); |
- ADD_METHOD("conicTo", ConicTo); |
- |
- context->Global()->Set(v8::String::NewFromUtf8( |
- gGlobal->getIsolate(), "Path2D"), constructor->GetFunction()); |
-} |
- |
-Path2D* Path2D::Unwrap(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast( |
- args.This()->GetInternalField(0)); |
- void* ptr = field->Value(); |
- return static_cast<Path2D*>(ptr); |
-} |
+ // Just once create the ObjectTemplate for what Path2D looks like in JS. |
+ if (gPath2DTemplate.IsEmpty()) { |
+ v8::Local<v8::ObjectTemplate> localTemplate = v8::ObjectTemplate::New(); |
-void Path2D::ClosePath(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- Path2D* path = Unwrap(args); |
- path->fSkPath.close(); |
-} |
+ // Add a field to store the pointer to a SkPath pointer. |
+ localTemplate->SetInternalFieldCount(1); |
-void Path2D::MoveTo(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 2) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 2 arguments required.")); |
- return; |
+ gPath2DTemplate.Reset(gGlobal->getIsolate(), localTemplate); |
} |
- double x = args[0]->NumberValue(); |
- double y = args[1]->NumberValue(); |
- Path2D* path = Unwrap(args); |
- path->fSkPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); |
-} |
+ v8::Handle<v8::ObjectTemplate> templ = |
+ v8::Local<v8::ObjectTemplate>::New(gGlobal->getIsolate(), gPath2DTemplate); |
-void Path2D::LineTo(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 2) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 2 arguments required.")); |
- return; |
- } |
- double x = args[0]->NumberValue(); |
- double y = args[1]->NumberValue(); |
- Path2D* path = Unwrap(args); |
- path->fSkPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); |
-} |
+ // Create an empty Path2D wrapper. |
+ v8::Local<v8::Object> result = templ->NewInstance(); |
-void Path2D::QuadraticCurveTo(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 4) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 4 arguments required.")); |
- return; |
- } |
- double cpx = args[0]->NumberValue(); |
- double cpy = args[1]->NumberValue(); |
- double x = args[2]->NumberValue(); |
- double y = args[3]->NumberValue(); |
- Path2D* path = Unwrap(args); |
- // TODO(jcgregorio) Doesn't handle the empty last path case correctly per |
- // the HTML 5 spec. |
- path->fSkPath.quadTo( |
- SkDoubleToScalar(cpx), SkDoubleToScalar(cpy), |
- SkDoubleToScalar(x), SkDoubleToScalar(y)); |
-} |
+ // Store the SkPath pointer in the JavaScript wrapper. |
+ result->SetInternalField(0, v8::External::New(gGlobal->getIsolate(), this)); |
+ gGlobal->getIsolate()->AdjustAmountOfExternalAllocatedMemory(sizeof(SkPath)); |
-void Path2D::BezierCurveTo(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 6) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 6 arguments required.")); |
- return; |
- } |
- double cp1x = args[0]->NumberValue(); |
- double cp1y = args[1]->NumberValue(); |
- double cp2x = args[2]->NumberValue(); |
- double cp2y = args[3]->NumberValue(); |
- double x = args[4]->NumberValue(); |
- double y = args[5]->NumberValue(); |
- Path2D* path = Unwrap(args); |
- // TODO(jcgregorio) Doesn't handle the empty last path case correctly per |
- // the HTML 5 spec. |
- path->fSkPath.cubicTo( |
- SkDoubleToScalar(cp1x), SkDoubleToScalar(cp1y), |
- SkDoubleToScalar(cp2x), SkDoubleToScalar(cp2y), |
- SkDoubleToScalar(x), SkDoubleToScalar(y)); |
+ // Make a weak persistent and set up the callback so we can delete the path pointer. |
+ // TODO(jcgregorio) Figure out why weakPath2DCallback never gets called and we leak. |
+ v8::Persistent<v8::Object> weak(gGlobal->getIsolate(), result); |
+ weak.SetWeak(this, weakPath2DCallback); |
+ this->handle_.Reset(gGlobal->getIsolate(), weak); |
} |
-void Path2D::Arc(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 5 && args.Length() != 6) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 5 or 6 args required.")); |
- return; |
- } |
- double x = args[0]->NumberValue(); |
- double y = args[1]->NumberValue(); |
- double radius = args[2]->NumberValue(); |
- double startAngle = args[3]->NumberValue(); |
- double endAngle = args[4]->NumberValue(); |
- bool antiClockwise = false; |
- if (args.Length() == 6) { |
- antiClockwise = args[5]->BooleanValue(); |
- } |
- double sweepAngle; |
- if (!antiClockwise) { |
- sweepAngle = endAngle - startAngle; |
- } else { |
- sweepAngle = startAngle - endAngle; |
- startAngle = endAngle; |
- } |
- |
- Path2D* path = Unwrap(args); |
- SkRect rect = { |
- SkDoubleToScalar(x-radius), |
- SkDoubleToScalar(y-radius), |
- SkDoubleToScalar(x+radius), |
- SkDoubleToScalar(y+radius) |
- }; |
- |
- path->fSkPath.addArc(rect, SkRadiansToDegrees(startAngle), |
- SkRadiansToDegrees(sweepAngle)); |
-} |
- |
-void Path2D::Rect(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 4) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 4 arguments required.")); |
- return; |
- } |
- double x = args[0]->NumberValue(); |
- double y = args[1]->NumberValue(); |
- double w = args[2]->NumberValue(); |
- double h = args[3]->NumberValue(); |
- |
- SkRect rect = { |
- SkDoubleToScalar(x), |
- SkDoubleToScalar(y), |
- SkDoubleToScalar(x) + SkDoubleToScalar(w), |
- SkDoubleToScalar(y) + SkDoubleToScalar(h) |
- }; |
- Path2D* path = Unwrap(args); |
- path->fSkPath.addRect(rect); |
-} |
- |
-void Path2D::Oval(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 4 && args.Length() != 5) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 4 or 5 args required.")); |
- return; |
- } |
- double x = args[0]->NumberValue(); |
- double y = args[1]->NumberValue(); |
- double radiusX = args[2]->NumberValue(); |
- double radiusY = args[3]->NumberValue(); |
- SkPath::Direction dir = SkPath::kCW_Direction; |
- if (args.Length() == 5 && !args[4]->BooleanValue()) { |
- dir = SkPath::kCCW_Direction; |
- } |
- Path2D* path = Unwrap(args); |
- SkRect rect = { |
- SkDoubleToScalar(x-radiusX), |
- SkDoubleToScalar(y-radiusX), |
- SkDoubleToScalar(x+radiusY), |
- SkDoubleToScalar(y+radiusY) |
- }; |
- |
- path->fSkPath.addOval(rect, dir); |
-} |
- |
-void Path2D::ConicTo(const v8::FunctionCallbackInfo<v8::Value>& args) { |
- if (args.Length() != 5) { |
- args.GetIsolate()->ThrowException( |
- v8::String::NewFromUtf8( |
- args.GetIsolate(), "Error: 5 args required.")); |
- return; |
- } |
- double x1 = args[0]->NumberValue(); |
- double y1 = args[1]->NumberValue(); |
- double x2 = args[2]->NumberValue(); |
- double y2 = args[3]->NumberValue(); |
- double w = args[4]->NumberValue(); |
- Path2D* path = Unwrap(args); |
- |
- path->fSkPath.conicTo( |
- SkDoubleToScalar(x1), |
- SkDoubleToScalar(y1), |
- SkDoubleToScalar(x2), |
- SkDoubleToScalar(y2), |
- SkDoubleToScalar(w) |
- ); |
+Path2D::~Path2D() { |
+ delete path_; |
+ handle_.Reset(); |
+ gGlobal->getIsolate()->AdjustAmountOfExternalAllocatedMemory(-sizeof(SkPath)); |
} |