blob: 4118a22b80769c512db06f1833ad2c256138d8a9 [file] [log] [blame]
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +00001/*
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
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000010#include "Path2D.h"
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000011#include "Global.h"
12
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000013Global* Path2D::gGlobal = NULL;
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000014
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000015void Path2D::ConstructPath(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000016 HandleScope handleScope(gGlobal->getIsolate());
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000017 Path2D* path = new Path2D();
commit-bot@chromium.orgb1639842014-01-08 15:14:09 +000018 args.This()->SetInternalField(
19 0, External::New(gGlobal->getIsolate(), path));
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000020}
21
22#define ADD_METHOD(name, fn) \
23 constructor->InstanceTemplate()->Set( \
24 String::NewFromUtf8( \
25 global->getIsolate(), name, \
26 String::kInternalizedString), \
commit-bot@chromium.orgb1639842014-01-08 15:14:09 +000027 FunctionTemplate::New(global->getIsolate(), fn))
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000028
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000029// Install the constructor in the global scope so Path2Ds can be constructed
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000030// in JS.
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000031void Path2D::AddToGlobal(Global* global) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000032 gGlobal = global;
33
34 // Create a stack-allocated handle scope.
35 HandleScope handleScope(gGlobal->getIsolate());
36
37 Handle<Context> context = gGlobal->getContext();
38
39 // Enter the scope so all operations take place in the scope.
40 Context::Scope contextScope(context);
41
42 Local<FunctionTemplate> constructor = FunctionTemplate::New(
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000043 gGlobal->getIsolate(), Path2D::ConstructPath);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000044 constructor->InstanceTemplate()->SetInternalFieldCount(1);
45
commit-bot@chromium.orgcd110182014-01-10 21:33:01 +000046 ADD_METHOD("closePath", ClosePath);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000047 ADD_METHOD("moveTo", MoveTo);
48 ADD_METHOD("lineTo", LineTo);
49 ADD_METHOD("quadraticCurveTo", QuadraticCurveTo);
50 ADD_METHOD("bezierCurveTo", BezierCurveTo);
51 ADD_METHOD("arc", Arc);
52 ADD_METHOD("rect", Rect);
commit-bot@chromium.orgcd110182014-01-10 21:33:01 +000053 ADD_METHOD("oval", Oval);
commit-bot@chromium.orge1df5652014-02-13 16:00:58 +000054 ADD_METHOD("conicTo", ConicTo);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000055
commit-bot@chromium.orgb1639842014-01-08 15:14:09 +000056 context->Global()->Set(String::NewFromUtf8(
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000057 gGlobal->getIsolate(), "Path2D"), constructor->GetFunction());
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000058}
59
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000060Path2D* Path2D::Unwrap(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000061 Handle<External> field = Handle<External>::Cast(
62 args.This()->GetInternalField(0));
63 void* ptr = field->Value();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000064 return static_cast<Path2D*>(ptr);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000065}
66
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000067void Path2D::ClosePath(const v8::FunctionCallbackInfo<Value>& args) {
68 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000069 path->fSkPath.close();
70}
71
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000072void Path2D::MoveTo(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000073 if (args.Length() != 2) {
74 args.GetIsolate()->ThrowException(
75 v8::String::NewFromUtf8(
76 args.GetIsolate(), "Error: 2 arguments required."));
77 return;
78 }
79 double x = args[0]->NumberValue();
80 double y = args[1]->NumberValue();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000081 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000082 path->fSkPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
83}
84
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000085void Path2D::LineTo(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000086 if (args.Length() != 2) {
87 args.GetIsolate()->ThrowException(
88 v8::String::NewFromUtf8(
89 args.GetIsolate(), "Error: 2 arguments required."));
90 return;
91 }
92 double x = args[0]->NumberValue();
93 double y = args[1]->NumberValue();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000094 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000095 path->fSkPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
96}
97
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000098void Path2D::QuadraticCurveTo(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000099 if (args.Length() != 4) {
100 args.GetIsolate()->ThrowException(
101 v8::String::NewFromUtf8(
102 args.GetIsolate(), "Error: 4 arguments required."));
103 return;
104 }
105 double cpx = args[0]->NumberValue();
106 double cpy = args[1]->NumberValue();
107 double x = args[2]->NumberValue();
108 double y = args[3]->NumberValue();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000109 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000110 // TODO(jcgregorio) Doesn't handle the empty last path case correctly per
111 // the HTML 5 spec.
112 path->fSkPath.quadTo(
113 SkDoubleToScalar(cpx), SkDoubleToScalar(cpy),
114 SkDoubleToScalar(x), SkDoubleToScalar(y));
115}
116
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000117void Path2D::BezierCurveTo(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000118 if (args.Length() != 6) {
119 args.GetIsolate()->ThrowException(
120 v8::String::NewFromUtf8(
121 args.GetIsolate(), "Error: 6 arguments required."));
122 return;
123 }
124 double cp1x = args[0]->NumberValue();
125 double cp1y = args[1]->NumberValue();
126 double cp2x = args[2]->NumberValue();
127 double cp2y = args[3]->NumberValue();
128 double x = args[4]->NumberValue();
129 double y = args[5]->NumberValue();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000130 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000131 // TODO(jcgregorio) Doesn't handle the empty last path case correctly per
132 // the HTML 5 spec.
133 path->fSkPath.cubicTo(
134 SkDoubleToScalar(cp1x), SkDoubleToScalar(cp1y),
135 SkDoubleToScalar(cp2x), SkDoubleToScalar(cp2y),
136 SkDoubleToScalar(x), SkDoubleToScalar(y));
137}
138
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000139void Path2D::Arc(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000140 if (args.Length() != 5 && args.Length() != 6) {
141 args.GetIsolate()->ThrowException(
142 v8::String::NewFromUtf8(
143 args.GetIsolate(), "Error: 5 or 6 args required."));
144 return;
145 }
146 double x = args[0]->NumberValue();
147 double y = args[1]->NumberValue();
148 double radius = args[2]->NumberValue();
149 double startAngle = args[3]->NumberValue();
150 double endAngle = args[4]->NumberValue();
151 bool antiClockwise = false;
152 if (args.Length() == 6) {
153 antiClockwise = args[5]->BooleanValue();
154 }
155 double sweepAngle;
156 if (!antiClockwise) {
157 sweepAngle = endAngle - startAngle;
158 } else {
159 sweepAngle = startAngle - endAngle;
160 startAngle = endAngle;
161 }
162
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000163 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000164 SkRect rect = {
165 SkDoubleToScalar(x-radius),
166 SkDoubleToScalar(y-radius),
167 SkDoubleToScalar(x+radius),
168 SkDoubleToScalar(y+radius)
169 };
170
171 path->fSkPath.addArc(rect, SkRadiansToDegrees(startAngle),
172 SkRadiansToDegrees(sweepAngle));
173}
174
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000175void Path2D::Rect(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000176 if (args.Length() != 4) {
177 args.GetIsolate()->ThrowException(
178 v8::String::NewFromUtf8(
179 args.GetIsolate(), "Error: 4 arguments required."));
180 return;
181 }
182 double x = args[0]->NumberValue();
183 double y = args[1]->NumberValue();
184 double w = args[2]->NumberValue();
185 double h = args[3]->NumberValue();
186
187 SkRect rect = {
188 SkDoubleToScalar(x),
189 SkDoubleToScalar(y),
190 SkDoubleToScalar(x) + SkDoubleToScalar(w),
191 SkDoubleToScalar(y) + SkDoubleToScalar(h)
192 };
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000193 Path2D* path = Unwrap(args);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +0000194 path->fSkPath.addRect(rect);
195}
commit-bot@chromium.orgcd110182014-01-10 21:33:01 +0000196
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000197void Path2D::Oval(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orgcd110182014-01-10 21:33:01 +0000198 if (args.Length() != 4 && args.Length() != 5) {
199 args.GetIsolate()->ThrowException(
200 v8::String::NewFromUtf8(
201 args.GetIsolate(), "Error: 4 or 5 args required."));
202 return;
203 }
204 double x = args[0]->NumberValue();
205 double y = args[1]->NumberValue();
206 double radiusX = args[2]->NumberValue();
207 double radiusY = args[3]->NumberValue();
208 SkPath::Direction dir = SkPath::kCW_Direction;
209 if (args.Length() == 5 && !args[4]->BooleanValue()) {
210 dir = SkPath::kCCW_Direction;
211 }
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000212 Path2D* path = Unwrap(args);
commit-bot@chromium.orgcd110182014-01-10 21:33:01 +0000213 SkRect rect = {
214 SkDoubleToScalar(x-radiusX),
215 SkDoubleToScalar(y-radiusX),
216 SkDoubleToScalar(x+radiusY),
217 SkDoubleToScalar(y+radiusY)
218 };
219
220 path->fSkPath.addOval(rect, dir);
221}
commit-bot@chromium.orge1df5652014-02-13 16:00:58 +0000222
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000223void Path2D::ConicTo(const v8::FunctionCallbackInfo<Value>& args) {
commit-bot@chromium.orge1df5652014-02-13 16:00:58 +0000224 if (args.Length() != 5) {
225 args.GetIsolate()->ThrowException(
226 v8::String::NewFromUtf8(
227 args.GetIsolate(), "Error: 5 args required."));
228 return;
229 }
230 double x1 = args[0]->NumberValue();
231 double y1 = args[1]->NumberValue();
232 double x2 = args[2]->NumberValue();
233 double y2 = args[3]->NumberValue();
234 double w = args[4]->NumberValue();
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +0000235 Path2D* path = Unwrap(args);
commit-bot@chromium.orge1df5652014-02-13 16:00:58 +0000236
237 path->fSkPath.conicTo(
238 SkDoubleToScalar(x1),
239 SkDoubleToScalar(y1),
240 SkDoubleToScalar(x2),
241 SkDoubleToScalar(y2),
242 SkDoubleToScalar(w)
243 );
244}