|
|
@ -9,6 +9,7 @@ |
|
|
|
#include <string.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include "Canvas.h" |
|
|
|
#include "Point.h" |
|
|
|
#include "Image.h" |
|
|
|
#include "ImageData.h" |
|
|
|
#include "CanvasRenderingContext2d.h" |
|
|
@ -97,6 +98,7 @@ Context2d::Initialize(Handle<Object> target) { |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "beginPath", BeginPath); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "closePath", ClosePath); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "arc", Arc); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "arcTo", ArcTo); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "setFont", SetFont); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "setShadowRGBA", SetShadowRGBA); |
|
|
|
NODE_SET_PROTOTYPE_METHOD(constructor, "setFillRGBA", SetFillRGBA); |
|
|
@ -1576,10 +1578,10 @@ Context2d::Arc(const Arguments &args) { |
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
if (!args[0]->IsNumber() |
|
|
|
||!args[1]->IsNumber() |
|
|
|
||!args[2]->IsNumber() |
|
|
|
||!args[3]->IsNumber() |
|
|
|
||!args[4]->IsNumber()) return Undefined(); |
|
|
|
|| !args[1]->IsNumber() |
|
|
|
|| !args[2]->IsNumber() |
|
|
|
|| !args[3]->IsNumber() |
|
|
|
|| !args[4]->IsNumber()) return Undefined(); |
|
|
|
|
|
|
|
bool anticlockwise = args[5]->BooleanValue(); |
|
|
|
|
|
|
@ -1604,3 +1606,115 @@ Context2d::Arc(const Arguments &args) { |
|
|
|
|
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Adds an arcTo point (x0,y0) to (x1,y1) with the given radius. |
|
|
|
* |
|
|
|
* Implementation influenced by WebKit. |
|
|
|
*/ |
|
|
|
|
|
|
|
Handle<Value> |
|
|
|
Context2d::ArcTo(const Arguments &args) { |
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
if (!args[0]->IsNumber() |
|
|
|
|| !args[1]->IsNumber() |
|
|
|
|| !args[2]->IsNumber() |
|
|
|
|| !args[3]->IsNumber() |
|
|
|
|| !args[4]->IsNumber()) return Undefined(); |
|
|
|
|
|
|
|
Context2d *context = ObjectWrap::Unwrap<Context2d>(args.This()); |
|
|
|
cairo_t *ctx = context->context(); |
|
|
|
|
|
|
|
// Current path point
|
|
|
|
double x, y; |
|
|
|
cairo_get_current_point(ctx, &x, &y); |
|
|
|
Point<float> p0(x, y); |
|
|
|
|
|
|
|
// Point (x0,y0)
|
|
|
|
Point<float> p1(args[0]->NumberValue(), args[1]->NumberValue()); |
|
|
|
|
|
|
|
// Point (x1,y1)
|
|
|
|
Point<float> p2(args[2]->NumberValue(), args[3]->NumberValue()); |
|
|
|
|
|
|
|
float radius = args[4]->NumberValue(); |
|
|
|
|
|
|
|
if ((p1.x == p0.x && p1.y == p0.y) |
|
|
|
|| (p1.x == p2.x && p1.y == p2.y) |
|
|
|
|| radius == 0.f) { |
|
|
|
cairo_line_to(ctx, p1.x, p1.y); |
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|
|
|
|
|
Point<float> p1p0((p0.x - p1.x),(p0.y - p1.y)); |
|
|
|
Point<float> p1p2((p2.x - p1.x),(p2.y - p1.y)); |
|
|
|
float p1p0_length = sqrtf(p1p0.x * p1p0.x + p1p0.y * p1p0.y); |
|
|
|
float p1p2_length = sqrtf(p1p2.x * p1p2.x + p1p2.y * p1p2.y); |
|
|
|
|
|
|
|
double cos_phi = (p1p0.x * p1p2.x + p1p0.y * p1p2.y) / (p1p0_length * p1p2_length); |
|
|
|
// all points on a line logic
|
|
|
|
if (-1 == cos_phi) { |
|
|
|
cairo_line_to(ctx, p1.x, p1.y); |
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|
|
|
|
|
if (1 == cos_phi) { |
|
|
|
// add infinite far away point
|
|
|
|
unsigned int max_length = 65535; |
|
|
|
double factor_max = max_length / p1p0_length; |
|
|
|
Point<float> ep((p0.x + factor_max * p1p0.x), (p0.y + factor_max * p1p0.y)); |
|
|
|
cairo_line_to(ctx, ep.x, ep.y); |
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|
|
|
|
|
float tangent = radius / tan(acos(cos_phi) / 2); |
|
|
|
float factor_p1p0 = tangent / p1p0_length; |
|
|
|
Point<float> t_p1p0((p1.x + factor_p1p0 * p1p0.x), (p1.y + factor_p1p0 * p1p0.y)); |
|
|
|
|
|
|
|
Point<float> orth_p1p0(p1p0.y, -p1p0.x); |
|
|
|
float orth_p1p0_length = sqrt(orth_p1p0.x * orth_p1p0.x + orth_p1p0.y * orth_p1p0.y); |
|
|
|
float factor_ra = radius / orth_p1p0_length; |
|
|
|
|
|
|
|
double cos_alpha = (orth_p1p0.x * p1p2.x + orth_p1p0.y * p1p2.y) / (orth_p1p0_length * p1p2_length); |
|
|
|
if (cos_alpha < 0.f) |
|
|
|
orth_p1p0 = Point<float>(-orth_p1p0.x, -orth_p1p0.y); |
|
|
|
|
|
|
|
Point<float> p((t_p1p0.x + factor_ra * orth_p1p0.x), (t_p1p0.y + factor_ra * orth_p1p0.y)); |
|
|
|
|
|
|
|
orth_p1p0 = Point<float>(-orth_p1p0.x, -orth_p1p0.y); |
|
|
|
float sa = acos(orth_p1p0.x / orth_p1p0_length); |
|
|
|
if (orth_p1p0.y < 0.f) |
|
|
|
sa = 2 * M_PI - sa; |
|
|
|
|
|
|
|
bool anticlockwise = false; |
|
|
|
|
|
|
|
float factor_p1p2 = tangent / p1p2_length; |
|
|
|
Point<float> t_p1p2((p1.x + factor_p1p2 * p1p2.x), (p1.y + factor_p1p2 * p1p2.y)); |
|
|
|
Point<float> orth_p1p2((t_p1p2.x - p.x),(t_p1p2.y - p.y)); |
|
|
|
float orth_p1p2_length = sqrtf(orth_p1p2.x * orth_p1p2.x + orth_p1p2.y * orth_p1p2.y); |
|
|
|
float ea = acos(orth_p1p2.x / orth_p1p2_length); |
|
|
|
|
|
|
|
if (orth_p1p2.y < 0) ea = 2 * M_PI - ea; |
|
|
|
if ((sa > ea) && ((sa - ea) < M_PI)) anticlockwise = true; |
|
|
|
if ((sa < ea) && ((ea - sa) > M_PI)) anticlockwise = true; |
|
|
|
|
|
|
|
cairo_line_to(ctx, t_p1p0.x, t_p1p0.y); |
|
|
|
|
|
|
|
if (anticlockwise && M_PI * 2 != radius) { |
|
|
|
cairo_arc_negative(ctx |
|
|
|
, p.x |
|
|
|
, p.y |
|
|
|
, radius |
|
|
|
, sa |
|
|
|
, ea); |
|
|
|
} else { |
|
|
|
cairo_arc(ctx |
|
|
|
, p.x |
|
|
|
, p.y |
|
|
|
, radius |
|
|
|
, sa |
|
|
|
, ea); |
|
|
|
} |
|
|
|
|
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|