Skip to content

Commit 4ce04af

Browse files
committedJul 17, 2020
Speed up fillStyle= and strokeStyle=
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.
1 parent 0d9ca88 commit 4ce04af

File tree

4 files changed

+31
-26
lines changed

4 files changed

+31
-26
lines changed
 

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ project adheres to [Semantic Versioning](http://semver.org/).
1212
* Switch prebuilds to GitHub actions in the Automattic/node-canvas repository.
1313
Previously these were in the [node-gfx/node-canvas-prebuilt](https://github.com/node-gfx/node-canvas-prebuilt)
1414
and triggered manually.
15+
* Speed up `fillStyle=` and `strokeStyle=`
1516
### Added
1617
* Export `rsvgVersion`.
1718
### Fixed

‎benchmarks/run.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ function done (benchmark, times, start, isAsync) {
6565
// node-canvas
6666

6767
bm('fillStyle= name', function () {
68-
ctx.fillStyle = 'transparent'
68+
for (let i = 0; i < 10000; i++) {
69+
ctx.fillStyle = '#fefefe'
70+
}
6971
})
7072

7173
bm('lineTo()', function () {

‎src/CanvasRenderingContext2d.cc

+26-24
Original file line numberDiff line numberDiff line change
@@ -1828,24 +1828,26 @@ NAN_GETTER(Context2d::GetFillStyle) {
18281828
NAN_SETTER(Context2d::SetFillStyle) {
18291829
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());
18301830

1831-
if (Nan::New(Gradient::constructor)->HasInstance(value) ||
1832-
Nan::New(Pattern::constructor)->HasInstance(value)) {
1833-
context->_fillStyle.Reset(value);
1834-
1831+
if (value->IsString()) {
1832+
MaybeLocal<String> mstr = Nan::To<String>(value);
1833+
if (mstr.IsEmpty()) return;
1834+
Local<String> str = mstr.ToLocalChecked();
1835+
context->_fillStyle.Reset();
1836+
context->_setFillColor(str);
1837+
} else if (value->IsObject()) {
18351838
Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
1836-
if (Nan::New(Gradient::constructor)->HasInstance(obj)){
1839+
if (Nan::New(Gradient::constructor)->HasInstance(obj)) {
1840+
context->_fillStyle.Reset(value);
18371841
Gradient *grad = Nan::ObjectWrap::Unwrap<Gradient>(obj);
18381842
context->state->fillGradient = grad->pattern();
1839-
} else if(Nan::New(Pattern::constructor)->HasInstance(obj)){
1843+
} else if (Nan::New(Pattern::constructor)->HasInstance(obj)) {
1844+
context->_fillStyle.Reset(value);
18401845
Pattern *pattern = Nan::ObjectWrap::Unwrap<Pattern>(obj);
18411846
context->state->fillPattern = pattern->pattern();
1847+
} else {
1848+
// TODO this is non-standard
1849+
Nan::ThrowTypeError("Gradient or Pattern expected");
18421850
}
1843-
} else {
1844-
MaybeLocal<String> mstr = Nan::To<String>(value);
1845-
if (mstr.IsEmpty()) return;
1846-
Local<String> str = mstr.ToLocalChecked();
1847-
context->_fillStyle.Reset();
1848-
context->_setFillColor(str);
18491851
}
18501852
}
18511853

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

1875-
if (Nan::New(Gradient::constructor)->HasInstance(value) ||
1876-
Nan::New(Pattern::constructor)->HasInstance(value)) {
1877-
context->_strokeStyle.Reset(value);
1878-
1877+
if (value->IsString()) {
1878+
MaybeLocal<String> mstr = Nan::To<String>(value);
1879+
if (mstr.IsEmpty()) return;
1880+
Local<String> str = mstr.ToLocalChecked();
1881+
context->_strokeStyle.Reset();
1882+
context->_setStrokeColor(str);
1883+
} else if (value->IsObject()) {
18791884
Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
1880-
if (Nan::New(Gradient::constructor)->HasInstance(obj)){
1885+
if (Nan::New(Gradient::constructor)->HasInstance(obj)) {
1886+
context->_strokeStyle.Reset(value);
18811887
Gradient *grad = Nan::ObjectWrap::Unwrap<Gradient>(obj);
18821888
context->state->strokeGradient = grad->pattern();
1883-
} else if(Nan::New(Pattern::constructor)->HasInstance(obj)){
1889+
} else if (Nan::New(Pattern::constructor)->HasInstance(obj)) {
1890+
context->_strokeStyle.Reset(value);
18841891
Pattern *pattern = Nan::ObjectWrap::Unwrap<Pattern>(obj);
18851892
context->state->strokePattern = pattern->pattern();
18861893
} else {
1894+
// TODO this is non-standard
18871895
return Nan::ThrowTypeError("Gradient or Pattern expected");
18881896
}
1889-
} else {
1890-
MaybeLocal<String> mstr = Nan::To<String>(value);
1891-
if (mstr.IsEmpty()) return;
1892-
Local<String> str = mstr.ToLocalChecked();
1893-
context->_strokeStyle.Reset();
1894-
context->_setStrokeColor(str);
18951897
}
18961898
}
18971899

‎test/canvas.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1756,7 +1756,7 @@ describe('Canvas', function () {
17561756
var canvas = createCanvas(2, 2);
17571757
var ctx = canvas.getContext('2d');
17581758

1759-
ctx.fillStyle = ['#808080'];
1759+
ctx.fillStyle = '#808080';
17601760
ctx.fillRect(0, 0, 2, 2);
17611761
var data = ctx.getImageData(0, 0, 2, 2).data;
17621762

0 commit comments

Comments
 (0)
Please sign in to comment.