Skip to content

Commit 2719837

Browse files
authored
Merge branch 'Automattic:master' into feature/convertToBlob
2 parents 2631428 + adf73ee commit 2719837

26 files changed

+712
-306
lines changed

.github/workflows/ci.yaml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ on:
77
paths-ignore:
88
- ".github/workflows/prebuild.yaml"
99

10-
jobs:
10+
jobs:
1111
Linux:
1212
name: Test on Linux
1313
runs-on: ubuntu-latest
1414
strategy:
1515
matrix:
16-
node: [10, 12, 14, 16]
16+
node: [10, 12, 14, 16, 18, 20]
1717
steps:
1818
- uses: actions/setup-node@v3
1919
with:
2020
node-version: ${{ matrix.node }}
21-
- uses: actions/checkout@v2
21+
- uses: actions/checkout@v3
2222
- name: Install Dependencies
2323
run: |
2424
sudo apt update
@@ -33,12 +33,12 @@ jobs:
3333
runs-on: windows-2019
3434
strategy:
3535
matrix:
36-
node: [10, 12, 14, 16]
36+
node: [10, 12, 14, 16, 18, 20]
3737
steps:
3838
- uses: actions/setup-node@v3
3939
with:
4040
node-version: ${{ matrix.node }}
41-
- uses: actions/checkout@v2
41+
- uses: actions/checkout@v3
4242
- name: Install Dependencies
4343
run: |
4444
Invoke-WebRequest "https://ftp-osl.osuosl.org/pub/gnome/binaries/win64/gtk+/2.22/gtk+-bundle_2.22.1-20101229_win64.zip" -OutFile "gtk.zip"
@@ -57,15 +57,16 @@ jobs:
5757
runs-on: macos-latest
5858
strategy:
5959
matrix:
60-
node: [10, 12, 14, 16]
60+
node: [10, 12, 14, 16, 18, 20]
6161
steps:
6262
- uses: actions/setup-node@v3
6363
with:
6464
node-version: ${{ matrix.node }}
65-
- uses: actions/checkout@v2
65+
- uses: actions/checkout@v3
6666
- name: Install Dependencies
6767
run: |
6868
brew update
69+
brew install python3 || : # python doesn't need to be linked
6970
brew install pkg-config cairo pango libpng jpeg giflib librsvg
7071
- name: Install
7172
run: npm install --build-from-source
@@ -79,7 +80,7 @@ jobs:
7980
- uses: actions/setup-node@v3
8081
with:
8182
node-version: 14
82-
- uses: actions/checkout@v2
83+
- uses: actions/checkout@v3
8384
- name: Install
8485
run: npm install --ignore-scripts
8586
- name: Lint

.github/workflows/prebuild.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
Linux:
2525
strategy:
2626
matrix:
27-
node: [8, 9, 10, 11, 12, 13, 14]
27+
node: [8, 9, 10, 11, 12, 13, 14, 16, 18, 20]
2828
canvas_tag: [] # e.g. "v2.6.1"
2929
name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, Linux
3030
runs-on: ubuntu-latest
@@ -97,7 +97,7 @@ jobs:
9797
macOS:
9898
strategy:
9999
matrix:
100-
node: [8, 9, 10, 11, 12, 13, 14]
100+
node: [8, 9, 10, 11, 12, 13, 14, 16, 18, 20]
101101
canvas_tag: [] # e.g. "v2.6.1"
102102
name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, macOS
103103
runs-on: macos-latest
@@ -163,7 +163,7 @@ jobs:
163163
Win:
164164
strategy:
165165
matrix:
166-
node: [8, 9, 10, 11, 12, 13, 14]
166+
node: [8, 9, 10, 11, 12, 13, 14, 16, 18, 20]
167167
canvas_tag: [] # e.g. "v2.6.1"
168168
name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, Windows
169169
runs-on: windows-latest

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,45 @@ project adheres to [Semantic Versioning](http://semver.org/).
88
(Unreleased)
99
==================
1010
### Changed
11+
* Defer the initialization of the `op` variable to the `default` switch case to avoid a compiler warning. (#2229)
12+
* Use a `default` switch case with a null statement if some enum values aren't suppsed to be handled, this avoids a compiler warning. (#2229)
13+
* Migrate from librsvg's deprecated `rsvg_handle_get_dimensions()` and `rsvg_handle_render_cairo()` functions to the new `rsvg_handle_get_intrinsic_size_in_pixels()` and `rsvg_handle_render_document()` respectively. (#2229)
14+
* Avoid calling virtual methods in constructors/destructors to avoid bypassing virtual dispatch. (#2229)
15+
* Remove unused private field `backend` in the `Backend` class. (#2229)
16+
* Add Node.js v20 to CI. (#2237)
1117
### Added
18+
* Added string tags to support class detection
1219
### Fixed
20+
* Fix a case of use-after-free. (#2229)
21+
* Fix usage of garbage value by filling the allocated memory entirely with zeros if it's not modified. (#2229)
22+
* Fix a potential memory leak. (#2229)
23+
24+
2.11.2
25+
==================
26+
### Fixed
27+
* Building on Windows in CI (and maybe other Windows configurations?) (#2216)
28+
29+
2.11.1
30+
==================
31+
### Fixed
32+
* Add missing property `canvas` to the `CanvasRenderingContext2D` type
33+
* Fixed glyph positions getting rounded, resulting text having a slight `letter-spacing` effect
34+
* Fixed `ctx.font` not being restored correctly after `ctx.restore()` (#1946)
35+
36+
2.11.0
37+
==================
38+
### Fixed
39+
* Replace triple-slash directive in types with own types to avoid polluting TS modules with globals ([#1656](https://github.com/Automattic/node-canvas/issues/1656))
40+
41+
2.10.2
42+
==================
43+
### Fixed
44+
* Fix `Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32.` ([#2025](https://github.com/Automattic/node-canvas/issues/2025))
45+
* `textBaseline` and `textAlign` were not saved/restored by `save()`/`restore()`. ([#1936](https://github.com/Automattic/node-canvas/issues/2029))
46+
* Update nan to v2.17.0 to ensure Node.js v18+ support.
47+
### Changed
48+
* Improve performance and memory usage of `save()`/`restore()`.
49+
* `save()`/`restore()` no longer have a maximum depth (previously 64 states).
1350

1451
2.10.1
1552
==================

Readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ This project is an implementation of the Web Canvas API and implements that API
9191
* [CanvasRenderingContext2D#patternQuality](#canvasrenderingcontext2dpatternquality)
9292
* [CanvasRenderingContext2D#quality](#canvasrenderingcontext2dquality)
9393
* [CanvasRenderingContext2D#textDrawingMode](#canvasrenderingcontext2dtextdrawingmode)
94-
* [CanvasRenderingContext2D#globalCompositeOperator = 'saturate'](#canvasrenderingcontext2dglobalcompositeoperator--saturate)
94+
* [CanvasRenderingContext2D#globalCompositeOperation = 'saturate'](#canvasrenderingcontext2dglobalcompositeoperation--saturate)
9595
* [CanvasRenderingContext2D#antialias](#canvasrenderingcontext2dantialias)
9696

9797
### createCanvas()

benchmarks/run.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ function done (benchmark, times, start, isAsync) {
6464

6565
// node-canvas
6666

67+
bm('save/restore', function () {
68+
for (let i = 0; i < 1000; i++) {
69+
const max = i & 15
70+
for (let j = 0; j < max; ++j) {
71+
ctx.save()
72+
}
73+
for (let j = 0; j < max; ++j) {
74+
ctx.restore()
75+
}
76+
}
77+
})
78+
6779
bm('fillStyle= name', function () {
6880
for (let i = 0; i < 10000; i++) {
6981
ctx.fillStyle = '#fefefe'

lib/bindings.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,40 @@ const bindings = require('../build/Release/canvas.node')
44

55
module.exports = bindings
66

7+
Object.defineProperty(bindings.Canvas.prototype, Symbol.toStringTag, {
8+
value: 'HTMLCanvasElement',
9+
configurable: true
10+
})
11+
12+
Object.defineProperty(bindings.Image.prototype, Symbol.toStringTag, {
13+
value: 'HTMLImageElement',
14+
configurable: true
15+
})
16+
717
bindings.ImageData.prototype.toString = function () {
818
return '[object ImageData]'
919
}
1020

21+
Object.defineProperty(bindings.ImageData.prototype, Symbol.toStringTag, {
22+
value: 'ImageData',
23+
configurable: true
24+
})
25+
1126
bindings.CanvasGradient.prototype.toString = function () {
1227
return '[object CanvasGradient]'
1328
}
29+
30+
Object.defineProperty(bindings.CanvasGradient.prototype, Symbol.toStringTag, {
31+
value: 'CanvasGradient',
32+
configurable: true
33+
})
34+
35+
Object.defineProperty(bindings.CanvasPattern.prototype, Symbol.toStringTag, {
36+
value: 'CanvasPattern',
37+
configurable: true
38+
})
39+
40+
Object.defineProperty(bindings.CanvasRenderingContext2d.prototype, Symbol.toStringTag, {
41+
value: 'CanvasRenderingContext2d',
42+
configurable: true
43+
})

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "canvas",
33
"description": "Canvas graphics API backed by Cairo",
4-
"version": "2.10.1",
4+
"version": "2.11.2",
55
"author": "TJ Holowaychuk <tj@learnboost.com>",
66
"main": "index.js",
77
"browser": "browser.js",
@@ -51,7 +51,7 @@
5151
"types": "types/index.d.ts",
5252
"dependencies": {
5353
"@mapbox/node-pre-gyp": "^1.0.0",
54-
"nan": "^2.15.0",
54+
"nan": "^2.17.0",
5555
"simple-get": "^3.0.3"
5656
},
5757
"devDependencies": {

src/Canvas.cc

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
"with at least a family (string) and optionally weight (string/number) " \
3636
"and style (string)."
3737

38+
#define CHECK_RECEIVER(prop) \
39+
if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { \
40+
Nan::ThrowTypeError("Method " #prop " called on incompatible receiver"); \
41+
return; \
42+
}
43+
3844
using namespace v8;
3945
using namespace std;
4046

@@ -64,10 +70,10 @@ Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
6470
#ifdef HAVE_JPEG
6571
Nan::SetPrototypeMethod(ctor, "streamJPEGSync", StreamJPEGSync);
6672
#endif
67-
SetProtoAccessor(proto, Nan::New("type").ToLocalChecked(), GetType, NULL, ctor);
68-
SetProtoAccessor(proto, Nan::New("stride").ToLocalChecked(), GetStride, NULL, ctor);
69-
SetProtoAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth, ctor);
70-
SetProtoAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight, ctor);
73+
Nan::SetAccessor(proto, Nan::New("type").ToLocalChecked(), GetType);
74+
Nan::SetAccessor(proto, Nan::New("stride").ToLocalChecked(), GetStride);
75+
Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth);
76+
Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);
7177

7278
Nan::SetTemplate(proto, "PNG_NO_FILTERS", Nan::New<Uint32>(PNG_NO_FILTERS));
7379
Nan::SetTemplate(proto, "PNG_FILTER_NONE", Nan::New<Uint32>(PNG_FILTER_NONE));
@@ -127,8 +133,9 @@ NAN_METHOD(Canvas::New) {
127133
}
128134

129135
if (!backend->isSurfaceValid()) {
136+
const char *error = backend->getError();
130137
delete backend;
131-
return Nan::ThrowError(backend->getError());
138+
return Nan::ThrowError(error);
132139
}
133140

134141
Canvas* canvas = new Canvas(backend);
@@ -144,6 +151,7 @@ NAN_METHOD(Canvas::New) {
144151
*/
145152

146153
NAN_GETTER(Canvas::GetType) {
154+
CHECK_RECEIVER(Canvas.GetType);
147155
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
148156
info.GetReturnValue().Set(Nan::New<String>(canvas->backend()->getName()).ToLocalChecked());
149157
}
@@ -152,6 +160,7 @@ NAN_GETTER(Canvas::GetType) {
152160
* Get stride.
153161
*/
154162
NAN_GETTER(Canvas::GetStride) {
163+
CHECK_RECEIVER(Canvas.GetStride);
155164
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
156165
info.GetReturnValue().Set(Nan::New<Number>(canvas->stride()));
157166
}
@@ -161,6 +170,7 @@ NAN_GETTER(Canvas::GetStride) {
161170
*/
162171

163172
NAN_GETTER(Canvas::GetWidth) {
173+
CHECK_RECEIVER(Canvas.GetWidth);
164174
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
165175
info.GetReturnValue().Set(Nan::New<Number>(canvas->getWidth()));
166176
}
@@ -170,6 +180,7 @@ NAN_GETTER(Canvas::GetWidth) {
170180
*/
171181

172182
NAN_SETTER(Canvas::SetWidth) {
183+
CHECK_RECEIVER(Canvas.SetWidth);
173184
if (value->IsNumber()) {
174185
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
175186
canvas->backend()->setWidth(Nan::To<uint32_t>(value).FromMaybe(0));
@@ -182,6 +193,7 @@ NAN_SETTER(Canvas::SetWidth) {
182193
*/
183194

184195
NAN_GETTER(Canvas::GetHeight) {
196+
CHECK_RECEIVER(Canvas.GetHeight);
185197
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
186198
info.GetReturnValue().Set(Nan::New<Number>(canvas->getHeight()));
187199
}
@@ -191,6 +203,7 @@ NAN_GETTER(Canvas::GetHeight) {
191203
*/
192204

193205
NAN_SETTER(Canvas::SetHeight) {
206+
CHECK_RECEIVER(Canvas.SetHeight);
194207
if (value->IsNumber()) {
195208
Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(info.This());
196209
canvas->backend()->setHeight(Nan::To<uint32_t>(value).FromMaybe(0));
@@ -773,13 +786,13 @@ NAN_METHOD(Canvas::RegisterFont) {
773786
NAN_METHOD(Canvas::DeregisterAllFonts) {
774787
// Unload all fonts from pango to free up memory
775788
bool success = true;
776-
789+
777790
std::for_each(font_face_list.begin(), font_face_list.end(), [&](FontFace& f) {
778791
if (!deregister_font( (unsigned char *)f.file_path )) success = false;
779792
pango_font_description_free(f.user_desc);
780793
pango_font_description_free(f.sys_desc);
781794
});
782-
795+
783796
font_face_list.clear();
784797
if (!success) Nan::ThrowError("Could not deregister one or more fonts");
785798
}
@@ -949,3 +962,5 @@ Local<Value>
949962
Canvas::Error(cairo_status_t status) {
950963
return Exception::Error(Nan::New<String>(cairo_status_to_string(status)).ToLocalChecked());
951964
}
965+
966+
#undef CHECK_RECEIVER

src/Canvas.h

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@
1111
#include <vector>
1212
#include <cstddef>
1313

14-
/*
15-
* Maxmimum states per context.
16-
* TODO: remove/resize
17-
*/
18-
19-
#ifndef CANVAS_MAX_STATES
20-
#define CANVAS_MAX_STATES 64
21-
#endif
22-
2314
/*
2415
* FontFace describes a font file in terms of one PangoFontDescription that
2516
* will resolve to it and one that the user describes it as (like @font-face)
@@ -31,6 +22,29 @@ class FontFace {
3122
unsigned char file_path[1024];
3223
};
3324

25+
enum text_baseline_t : uint8_t {
26+
TEXT_BASELINE_ALPHABETIC = 0,
27+
TEXT_BASELINE_TOP = 1,
28+
TEXT_BASELINE_BOTTOM = 2,
29+
TEXT_BASELINE_MIDDLE = 3,
30+
TEXT_BASELINE_IDEOGRAPHIC = 4,
31+
TEXT_BASELINE_HANGING = 5
32+
};
33+
34+
enum text_align_t : int8_t {
35+
TEXT_ALIGNMENT_LEFT = -1,
36+
TEXT_ALIGNMENT_CENTER = 0,
37+
TEXT_ALIGNMENT_RIGHT = 1,
38+
// Currently same as LEFT and RIGHT without RTL support:
39+
TEXT_ALIGNMENT_START = -2,
40+
TEXT_ALIGNMENT_END = 2
41+
};
42+
43+
enum canvas_draw_mode_t : uint8_t {
44+
TEXT_DRAW_PATHS,
45+
TEXT_DRAW_GLYPHS
46+
};
47+
3448
/*
3549
* Canvas.
3650
*/

0 commit comments

Comments
 (0)