Skip to content

Commit f2e073c

Browse files
committed
experimental: buffer lineTo calls in JS
1 parent 604db27 commit f2e073c

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
lines changed

benchmarks/run.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,12 @@ function done (benchmark, times, start, isAsync) {
6464

6565
// node-canvas
6666

67-
bm('fillStyle= name', function () {
68-
for (let i = 0; i < 10000; i++) {
69-
ctx.fillStyle = '#fefefe'
70-
}
71-
})
7267

7368
bm('lineTo()', function () {
7469
ctx.lineTo(0, 50)
70+
ctx.lineTo(10, 10)
71+
ctx.lineTo(20, 75)
72+
ctx.lineTo(30, 50)
7573
})
7674

7775
bm('arc()', function () {

lib/context2d.js

+9
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,12 @@ const { DOMMatrix } = require('./DOMMatrix')
1212

1313
bindings.CanvasRenderingContext2dInit(DOMMatrix, parseFont)
1414
module.exports = bindings.CanvasRenderingContext2d
15+
16+
bindings.CanvasRenderingContext2d.prototype.lineTo = function (x, y) {
17+
this._pts[this._ptidx++] = x;
18+
this._pts[this._ptidx++] = y;
19+
if (this._ptidx === 20) {
20+
this.linesTo(this._pts);
21+
this._ptidx = 0;
22+
}
23+
}

src/CanvasRenderingContext2d.cc

+50-3
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ inline static bool checkArgs(const Nan::FunctionCallbackInfo<Value> &info, doubl
7777
double val = Nan::To<double>(info[i]).FromMaybe(0);
7878

7979
if (areArgsValid) {
80-
if (val != val ||
81-
val == std::numeric_limits<double>::infinity() ||
82-
val == -std::numeric_limits<double>::infinity()) {
80+
if (!std::isfinite(val)) {
8381
// We should continue the loop instead of returning immediately
8482
// See https://html.spec.whatwg.org/multipage/canvas.html
8583

@@ -140,6 +138,7 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
140138
Nan::SetPrototypeMethod(ctor, "measureText", MeasureText);
141139
Nan::SetPrototypeMethod(ctor, "moveTo", MoveTo);
142140
Nan::SetPrototypeMethod(ctor, "lineTo", LineTo);
141+
Nan::SetPrototypeMethod(ctor, "linesTo", LinesTo);
143142
Nan::SetPrototypeMethod(ctor, "bezierCurveTo", BezierCurveTo);
144143
Nan::SetPrototypeMethod(ctor, "quadraticCurveTo", QuadraticCurveTo);
145144
Nan::SetPrototypeMethod(ctor, "beginPath", BeginPath);
@@ -723,6 +722,15 @@ NAN_METHOD(Context2d::New) {
723722
Context2d *context = new Context2d(canvas);
724723

725724
context->Wrap(info.This());
725+
726+
Nan::Set(info.This(),
727+
Nan::New<String>("_ptidx").ToLocalChecked(),
728+
Nan::New<Number>(0)).Check();
729+
Local<Float64Array> pts = Float64Array::New(ArrayBuffer::New(Isolate::GetCurrent(), 8 * 10 * 2), 0, 10 * 2);
730+
Nan::Set(info.This(),
731+
Nan::New<String>("_pts").ToLocalChecked(),
732+
pts).Check();
733+
726734
info.GetReturnValue().Set(info.This());
727735
}
728736

@@ -2363,6 +2371,20 @@ NAN_METHOD(Context2d::Fill) {
23632371

23642372
NAN_METHOD(Context2d::Stroke) {
23652373
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());
2374+
2375+
uint32_t ptidx = Nan::To<uint32_t>(Nan::Get(info.This(), Nan::New<String>("_ptidx").ToLocalChecked()).ToLocalChecked()).FromJust();
2376+
if (ptidx > 0) {
2377+
Local<Float64Array> pointsArray = Nan::Get(info.This(), Nan::New<String>("_pts").ToLocalChecked()).ToLocalChecked().As<Float64Array>();
2378+
Nan::TypedArrayContents<double> typedArrayContents(pointsArray);
2379+
double* points = *typedArrayContents;
2380+
for (uint32_t i = 0; i < ptidx; i += 2) {
2381+
cairo_line_to(context->context(), points[i], points[i + 1]);
2382+
}
2383+
Nan::Set(info.This(),
2384+
Nan::New<String>("_ptidx").ToLocalChecked(),
2385+
Nan::New<Number>(0)).Check();
2386+
}
2387+
23662388
context->stroke(true);
23672389
}
23682390

@@ -2511,6 +2533,17 @@ NAN_METHOD(Context2d::LineTo) {
25112533
cairo_line_to(context->context(), args[0], args[1]);
25122534
}
25132535

2536+
NAN_METHOD(Context2d::LinesTo) {
2537+
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());
2538+
2539+
Local<Float64Array> pointsArray = info[0].As<Float64Array>();
2540+
Nan::TypedArrayContents<double> typedArrayContents(pointsArray);
2541+
double* points = *typedArrayContents;
2542+
for (uint32_t i = 0; i < 20; i += 2) {
2543+
cairo_line_to(context->context(), points[i], points[i + 1]);
2544+
}
2545+
}
2546+
25142547
/*
25152548
* Creates a new subpath at the given point.
25162549
*/
@@ -2521,6 +2554,20 @@ NAN_METHOD(Context2d::MoveTo) {
25212554
return;
25222555

25232556
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());
2557+
2558+
uint32_t ptidx = Nan::To<uint32_t>(Nan::Get(info.This(), Nan::New<String>("_ptidx").ToLocalChecked()).ToLocalChecked()).FromJust();
2559+
if (ptidx > 0) {
2560+
Local<Float64Array> pointsArray = Nan::Get(info.This(), Nan::New<String>("_pts").ToLocalChecked()).ToLocalChecked().As<Float64Array>();
2561+
Nan::TypedArrayContents<double> typedArrayContents(pointsArray);
2562+
double* points = *typedArrayContents;
2563+
for (uint32_t i = 0; i < ptidx; i += 2) {
2564+
cairo_line_to(context->context(), points[i], points[i + 1]);
2565+
}
2566+
Nan::Set(info.This(),
2567+
Nan::New<String>("_ptidx").ToLocalChecked(),
2568+
Nan::New<Number>(0)).Check();
2569+
}
2570+
25242571
cairo_move_to(context->context(), args[0], args[1]);
25252572
}
25262573

src/CanvasRenderingContext2d.h

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class Context2d: public Nan::ObjectWrap {
9999
static NAN_METHOD(BezierCurveTo);
100100
static NAN_METHOD(QuadraticCurveTo);
101101
static NAN_METHOD(LineTo);
102+
static NAN_METHOD(LinesTo);
102103
static NAN_METHOD(MoveTo);
103104
static NAN_METHOD(FillRect);
104105
static NAN_METHOD(StrokeRect);

0 commit comments

Comments
 (0)