aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar jcgregorio <jcgregorio@google.com>2014-10-29 05:33:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-29 05:33:28 -0700
commite001da2558d936fca377e4041ca150ff95c85104 (patch)
tree6ae9cc95eed919a1ce2cb3d846dcaa23c2dfda17 /experimental
parent79f8faeea2692d2948c0f634e956d1e7fc8333e0 (diff)
SkV8Sample: Now with Path2D and Path2DBuilder.
Diffstat (limited to 'experimental')
-rw-r--r--experimental/SkV8Example/DrawingMethods.cpp2
-rw-r--r--experimental/SkV8Example/Path2D.cpp245
-rw-r--r--experimental/SkV8Example/Path2D.h47
-rw-r--r--experimental/SkV8Example/Path2DBuilder.cpp261
-rw-r--r--experimental/SkV8Example/Path2DBuilder.h53
-rw-r--r--experimental/SkV8Example/SkV8Example.cpp7
-rw-r--r--experimental/SkV8Example/js/sample.js27
7 files changed, 388 insertions, 254 deletions
diff --git a/experimental/SkV8Example/DrawingMethods.cpp b/experimental/SkV8Example/DrawingMethods.cpp
index fdc8dc7d63..5fcdd6a5e1 100644
--- a/experimental/SkV8Example/DrawingMethods.cpp
+++ b/experimental/SkV8Example/DrawingMethods.cpp
@@ -114,7 +114,7 @@ void DrawingMethods::DrawPath(const v8::FunctionCallbackInfo<v8::Value>& args) {
fillStyle.setColor(SK_ColorBLACK);
fillStyle.setAntiAlias(true);
fillStyle.setStyle(SkPaint::kFill_Style);
- canvas->drawPath(path->getSkPath(), fillStyle);
+ canvas->drawPath(*(path->path()), fillStyle);
}
diff --git a/experimental/SkV8Example/Path2D.cpp b/experimental/SkV8Example/Path2D.cpp
index 5956f69de3..dded688167 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));
}
diff --git a/experimental/SkV8Example/Path2D.h b/experimental/SkV8Example/Path2D.h
index 93c1299c61..4ac9877fd7 100644
--- a/experimental/SkV8Example/Path2D.h
+++ b/experimental/SkV8Example/Path2D.h
@@ -17,36 +17,35 @@
class Global;
+// Path2D bridges between JS and SkPath.
class Path2D : SkNoncopyable {
public:
- Path2D() : fSkPath() {}
- virtual ~Path2D() {}
-
- const SkPath& getSkPath() { return fSkPath; }
-
- // The JS Path2D constuctor implementation.
- static void ConstructPath(const v8::FunctionCallbackInfo<v8::Value>& args);
-
- // Add the Path2D JS constructor to the global context.
- static void AddToGlobal(Global* global);
-
- // Path2D JS methods.
- static void ClosePath(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void MoveTo(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void LineTo(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void QuadraticCurveTo(
- const v8::FunctionCallbackInfo<v8::Value>& args);
- static void BezierCurveTo(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void Arc(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void Rect(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void Oval(const v8::FunctionCallbackInfo<v8::Value>& args);
- static void ConicTo(const v8::FunctionCallbackInfo<v8::Value>& args);
+ Path2D(SkPath* path);
+ virtual ~Path2D();
+
+ static void AddToGlobal(Global* global) {
+ gGlobal = global;
+ }
+
+ v8::Persistent<v8::Object>& persistent() {
+ return handle_;
+ }
+
+ SkPath* path() {
+ return path_;
+ }
+
private:
- SkPath fSkPath;
+ // The handle to this object in JS space.
+ v8::Persistent<v8::Object> handle_;
- static Path2D* Unwrap(const v8::FunctionCallbackInfo<v8::Value>& args);
+ SkPath* path_;
+ // The global context we are running in.
static Global* gGlobal;
+
+ // The template for what a JS Path2D object looks like.
+ static v8::Persistent<v8::ObjectTemplate> gPath2DTemplate;
};
#endif
diff --git a/experimental/SkV8Example/Path2DBuilder.cpp b/experimental/SkV8Example/Path2DBuilder.cpp
new file mode 100644
index 0000000000..ad05668139
--- /dev/null
+++ b/experimental/SkV8Example/Path2DBuilder.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include "Global.h"
+#include "Path2DBuilder.h"
+#include "Path2D.h"
+#include "SkPath.h"
+
+Global* Path2DBuilder::gGlobal = NULL;
+
+void Path2DBuilder::ConstructPath(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::HandleScope handleScope(gGlobal->getIsolate());
+ Path2DBuilder* path = new Path2DBuilder();
+ args.This()->SetInternalField(
+ 0, v8::External::New(gGlobal->getIsolate(), path));
+}
+
+#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 Path2DBuilders can be constructed
+// in JS.
+void Path2DBuilder::AddToGlobal(Global* global) {
+ gGlobal = global;
+
+ // Create a stack-allocated handle scope.
+ 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(), Path2DBuilder::ConstructPath);
+ constructor->InstanceTemplate()->SetInternalFieldCount(1);
+
+ ADD_METHOD("close", 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);
+
+ ADD_METHOD("finalize", Finalize);
+
+ context->Global()->Set(v8::String::NewFromUtf8(
+ gGlobal->getIsolate(), "Path2DBuilder"), constructor->GetFunction());
+}
+
+Path2DBuilder* Path2DBuilder::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<Path2DBuilder*>(ptr);
+}
+
+void Path2DBuilder::ClosePath(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Path2DBuilder* path = Unwrap(args);
+ path->fSkPath.close();
+}
+
+void Path2DBuilder::MoveTo(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();
+ Path2DBuilder* path = Unwrap(args);
+ path->fSkPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
+}
+
+void Path2DBuilder::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();
+ Path2DBuilder* path = Unwrap(args);
+ path->fSkPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
+}
+
+void Path2DBuilder::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();
+ Path2DBuilder* 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));
+}
+
+void Path2DBuilder::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();
+ Path2DBuilder* 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));
+}
+
+void Path2DBuilder::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;
+ }
+
+ Path2DBuilder* 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 Path2DBuilder::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)
+ };
+ Path2DBuilder* path = Unwrap(args);
+ path->fSkPath.addRect(rect);
+}
+
+void Path2DBuilder::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;
+ }
+ Path2DBuilder* path = Unwrap(args);
+ SkRect rect = {
+ SkDoubleToScalar(x-radiusX),
+ SkDoubleToScalar(y-radiusX),
+ SkDoubleToScalar(x+radiusY),
+ SkDoubleToScalar(y+radiusY)
+ };
+
+ path->fSkPath.addOval(rect, dir);
+}
+
+void Path2DBuilder::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();
+ Path2DBuilder* path = Unwrap(args);
+
+ path->fSkPath.conicTo(
+ SkDoubleToScalar(x1),
+ SkDoubleToScalar(y1),
+ SkDoubleToScalar(x2),
+ SkDoubleToScalar(y2),
+ SkDoubleToScalar(w)
+ );
+}
+
+void Path2DBuilder::Finalize(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Path2DBuilder* path = Unwrap(args);
+
+ // Build Path2D from out fSkPath and return it.
+ SkPath* skPath = new SkPath(path->fSkPath);
+
+ path->fSkPath.reset();
+
+ Path2D* pathWrap = new Path2D(skPath);
+
+ args.GetReturnValue().Set(pathWrap->persistent());
+}
diff --git a/experimental/SkV8Example/Path2DBuilder.h b/experimental/SkV8Example/Path2DBuilder.h
new file mode 100644
index 0000000000..da9bddcb06
--- /dev/null
+++ b/experimental/SkV8Example/Path2DBuilder.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#ifndef SkV8Example_Path2DBuilder_DEFINED
+#define SkV8Example_Path2DBuilder_DEFINED
+
+#include <v8.h>
+
+#include "SkPath.h"
+#include "SkTypes.h"
+
+class Global;
+
+class Path2DBuilder : SkNoncopyable {
+public:
+ Path2DBuilder() : fSkPath() {}
+ virtual ~Path2DBuilder() {}
+
+ const SkPath& getSkPath() { return fSkPath; }
+
+ // The JS Path2DBuilder constuctor implementation.
+ static void ConstructPath(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ // Add the Path2DBuilder JS constructor to the global context.
+ static void AddToGlobal(Global* global);
+
+ // Path2DBuilder JS methods.
+ static void ClosePath(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void MoveTo(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void LineTo(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void QuadraticCurveTo(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void BezierCurveTo(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void Arc(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void Rect(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void Oval(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ConicTo(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void Finalize(const v8::FunctionCallbackInfo<v8::Value>& args);
+private:
+ SkPath fSkPath;
+
+ static Path2DBuilder* Unwrap(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ static Global* gGlobal;
+};
+
+#endif
diff --git a/experimental/SkV8Example/SkV8Example.cpp b/experimental/SkV8Example/SkV8Example.cpp
index 84fe648c90..d537fd4d38 100644
--- a/experimental/SkV8Example/SkV8Example.cpp
+++ b/experimental/SkV8Example/SkV8Example.cpp
@@ -13,6 +13,7 @@
#include "Global.h"
#include "JsContext.h"
#include "Path2D.h"
+#include "Path2DBuilder.h"
#include "gl/GrGLUtil.h"
#include "gl/GrGLDefines.h"
@@ -129,6 +130,8 @@ void SkV8ExampleWindow::onSizeChange() {
#endif
}
+Global* global = NULL;
+
void SkV8ExampleWindow::onDraw(SkCanvas* canvas) {
canvas->save();
@@ -164,6 +167,7 @@ void SkV8ExampleWindow::onHandleInval(const SkIRect& rect) {
SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
printf("Started\n");
+ v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
SkCommandLineFlags::Parse(argc, argv);
v8::V8::InitializeICU();
@@ -176,7 +180,7 @@ SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
v8::HandleScope handle_scope(isolate);
isolate->Enter();
- Global* global = new Global(isolate);
+ global = new Global(isolate);
// Set up things to look like a browser by creating
@@ -210,6 +214,7 @@ SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
printf("Could not load file: %s.\n", FLAGS_infile[0]);
exit(1);
}
+ Path2DBuilder::AddToGlobal(global);
Path2D::AddToGlobal(global);
if (!global->parseScript(script)) {
diff --git a/experimental/SkV8Example/js/sample.js b/experimental/SkV8Example/js/sample.js
index 7e7e40a918..f04da337e2 100644
--- a/experimental/SkV8Example/js/sample.js
+++ b/experimental/SkV8Example/js/sample.js
@@ -2,23 +2,28 @@
* @fileoverview Sample onDraw script for use with SkV8Example.
*/
var onDraw = function(){
- var tick = 0;
- var p = new Path2D();
- p.rect(0, 0, 200, 200);
+ var ticks = 0;
+ var b = new Path2DBuilder();
+ b.rect(0, 0, 200, 200);
+ var p = b.finalize();
function f(context) {
- tick += 0.1;
+ ticks += 1;
context.translate(context.width/2, context.height/2);
- context.rotate(tick);
+ context.rotate(ticks/10);
context.drawPath(p);
+
+ inval();
};
+
+ function onTimeout() {
+ console.log(ticks);
+ ticks = 0;
+ setTimeout(onTimeout, 1000);
+ }
+ setTimeout(onTimeout, 1000);
+
return f;
}();
-function onTimeout() {
- inval();
- print(setTimeout(onTimeout, 33));
-}
-
-setTimeout(onTimeout, 33);