| 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));
|
| }
|
|
|