Skip to content

Commit

Permalink
Speed up fillStyle= and strokeStyle=
Browse files Browse the repository at this point in the history
Roughly 2x performance improvement.
- Don't create extra Local<FunctionTemplate> handles
- Don't create any Local<FunctionTemplate> handles if the value is a string

I have no idea what that test case was doing.
  • Loading branch information
zbjornson committed Jul 17, 2020
1 parent 0d9ca88 commit 4ce04af
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ project adheres to [Semantic Versioning](http://semver.org/).
* Switch prebuilds to GitHub actions in the Automattic/node-canvas repository.
Previously these were in the [node-gfx/node-canvas-prebuilt](https://github.com/node-gfx/node-canvas-prebuilt)
and triggered manually.
* Speed up `fillStyle=` and `strokeStyle=`
### Added
* Export `rsvgVersion`.
### Fixed
Expand Down
4 changes: 3 additions & 1 deletion benchmarks/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ function done (benchmark, times, start, isAsync) {
// node-canvas

bm('fillStyle= name', function () {
ctx.fillStyle = 'transparent'
for (let i = 0; i < 10000; i++) {
ctx.fillStyle = '#fefefe'
}
})

bm('lineTo()', function () {
Expand Down
50 changes: 26 additions & 24 deletions src/CanvasRenderingContext2d.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1828,24 +1828,26 @@ NAN_GETTER(Context2d::GetFillStyle) {
NAN_SETTER(Context2d::SetFillStyle) {
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());

if (Nan::New(Gradient::constructor)->HasInstance(value) ||
Nan::New(Pattern::constructor)->HasInstance(value)) {
context->_fillStyle.Reset(value);

if (value->IsString()) {
MaybeLocal<String> mstr = Nan::To<String>(value);
if (mstr.IsEmpty()) return;
Local<String> str = mstr.ToLocalChecked();
context->_fillStyle.Reset();
context->_setFillColor(str);
} else if (value->IsObject()) {
Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
if (Nan::New(Gradient::constructor)->HasInstance(obj)){
if (Nan::New(Gradient::constructor)->HasInstance(obj)) {
context->_fillStyle.Reset(value);
Gradient *grad = Nan::ObjectWrap::Unwrap<Gradient>(obj);
context->state->fillGradient = grad->pattern();
} else if(Nan::New(Pattern::constructor)->HasInstance(obj)){
} else if (Nan::New(Pattern::constructor)->HasInstance(obj)) {
context->_fillStyle.Reset(value);
Pattern *pattern = Nan::ObjectWrap::Unwrap<Pattern>(obj);
context->state->fillPattern = pattern->pattern();
} else {
// TODO this is non-standard
Nan::ThrowTypeError("Gradient or Pattern expected");
}
} else {
MaybeLocal<String> mstr = Nan::To<String>(value);
if (mstr.IsEmpty()) return;
Local<String> str = mstr.ToLocalChecked();
context->_fillStyle.Reset();
context->_setFillColor(str);
}
}

Expand All @@ -1872,26 +1874,26 @@ NAN_GETTER(Context2d::GetStrokeStyle) {
NAN_SETTER(Context2d::SetStrokeStyle) {
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());

if (Nan::New(Gradient::constructor)->HasInstance(value) ||
Nan::New(Pattern::constructor)->HasInstance(value)) {
context->_strokeStyle.Reset(value);

if (value->IsString()) {
MaybeLocal<String> mstr = Nan::To<String>(value);
if (mstr.IsEmpty()) return;
Local<String> str = mstr.ToLocalChecked();
context->_strokeStyle.Reset();
context->_setStrokeColor(str);
} else if (value->IsObject()) {
Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
if (Nan::New(Gradient::constructor)->HasInstance(obj)){
if (Nan::New(Gradient::constructor)->HasInstance(obj)) {
context->_strokeStyle.Reset(value);
Gradient *grad = Nan::ObjectWrap::Unwrap<Gradient>(obj);
context->state->strokeGradient = grad->pattern();
} else if(Nan::New(Pattern::constructor)->HasInstance(obj)){
} else if (Nan::New(Pattern::constructor)->HasInstance(obj)) {
context->_strokeStyle.Reset(value);
Pattern *pattern = Nan::ObjectWrap::Unwrap<Pattern>(obj);
context->state->strokePattern = pattern->pattern();
} else {
// TODO this is non-standard
return Nan::ThrowTypeError("Gradient or Pattern expected");
}
} else {
MaybeLocal<String> mstr = Nan::To<String>(value);
if (mstr.IsEmpty()) return;
Local<String> str = mstr.ToLocalChecked();
context->_strokeStyle.Reset();
context->_setStrokeColor(str);
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/canvas.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1756,7 +1756,7 @@ describe('Canvas', function () {
var canvas = createCanvas(2, 2);
var ctx = canvas.getContext('2d');

ctx.fillStyle = ['#808080'];
ctx.fillStyle = '#808080';
ctx.fillRect(0, 0, 2, 2);
var data = ctx.getImageData(0, 0, 2, 2).data;

Expand Down

0 comments on commit 4ce04af

Please sign in to comment.