@napi-rs/canvas 0.1.25 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # `skr canvas`
2
2
 
3
3
  ![CI](https://github.com/Brooooooklyn/canvas/workflows/CI/badge.svg)
4
- ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm104-hotpink)
4
+ ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm105-hotpink)
5
5
  [![install size](https://packagephobia.com/badge?p=@napi-rs/canvas)](https://packagephobia.com/result?p=@napi-rs/canvas)
6
6
  [![Downloads](https://img.shields.io/npm/dm/@napi-rs/canvas.svg?sanitize=true)](https://npmcharts.com/compare/@napi-rs/canvas?minimal=true)
7
7
 
@@ -76,7 +76,7 @@ ctx.closePath()
76
76
  ctx.stroke()
77
77
 
78
78
  async function main() {
79
- const pngData = await canvas.encode('png') // JPEG and WebP is also supported
79
+ const pngData = await canvas.encode('png') // JPEG, AVIF and WebP are also supported
80
80
  // encoding in libuv thread pool, non-blocking
81
81
  await promises.writeFile(join(__dirname, 'simple.png'), pngData)
82
82
  }
package/index.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ /// <reference lib="dom" />
2
+
3
+ // Clear all type of caches in Skia
4
+ export function clearAllCache(): void
5
+
1
6
  export interface DOMMatrix2DInit {
2
7
  a: number
3
8
  b: number
@@ -354,34 +359,34 @@ interface IGlobalFonts {
354
359
 
355
360
  export const GlobalFonts: IGlobalFonts
356
361
 
357
- export const enum PathOp {
362
+ export enum PathOp {
358
363
  Difference = 0, // subtract the op path from the first path
359
364
  Intersect = 1, // intersect the two paths
360
365
  Union = 2, // union (inclusive-or) the two paths
361
- XOR = 3, // exclusive-or the two paths
366
+ Xor = 3, // exclusive-or the two paths
362
367
  ReverseDifference = 4, // subtract the first path from the op path
363
368
  }
364
369
 
365
- export const enum FillType {
370
+ export enum FillType {
366
371
  Winding = 0,
367
372
  EvenOdd = 1,
368
373
  InverseWinding = 2,
369
374
  InverseEvenOdd = 3,
370
375
  }
371
376
 
372
- export const enum StrokeJoin {
377
+ export enum StrokeJoin {
373
378
  Miter = 0,
374
379
  Round = 1,
375
380
  Bevel = 2,
376
381
  }
377
382
 
378
- export const enum StrokeCap {
383
+ export enum StrokeCap {
379
384
  Butt = 0,
380
385
  Round = 1,
381
386
  Square = 2,
382
387
  }
383
388
 
384
- export const enum SvgExportFlag {
389
+ export enum SvgExportFlag {
385
390
  ConvertTextToPaths = 0x01,
386
391
  NoPrettyXML = 0x02,
387
392
  RelativePathEncoding = 0x04,
@@ -390,9 +395,9 @@ export const enum SvgExportFlag {
390
395
  export function convertSVGTextToPath(svg: Buffer | string): Buffer
391
396
 
392
397
  export interface LoadImageOptions {
393
- alt?: string,
394
- maxRedirects?: number,
395
- requestOptions?: import('http').RequestOptions,
398
+ alt?: string
399
+ maxRedirects?: number
400
+ requestOptions?: import('http').RequestOptions
396
401
  }
397
402
 
398
403
  export function loadImage(
package/index.js CHANGED
@@ -2,6 +2,7 @@ const { platform, homedir } = require('os')
2
2
  const { join } = require('path')
3
3
 
4
4
  const {
5
+ clearAllCache,
5
6
  CanvasRenderingContext2D,
6
7
  CanvasElement,
7
8
  createContext,
@@ -11,95 +12,35 @@ const {
11
12
  Image,
12
13
  CanvasPattern,
13
14
  GlobalFonts,
14
- convertSVGTextToPath: _convertSVGTextToPath,
15
+ PathOp,
16
+ FillType,
17
+ StrokeJoin,
18
+ StrokeCap,
19
+ convertSVGTextToPath,
15
20
  } = require('./js-binding')
16
21
 
17
22
  const { DOMPoint, DOMMatrix, DOMRect } = require('./geometry')
18
23
 
19
24
  const loadImage = require('./load-image')
20
25
 
21
- const StrokeJoin = {
22
- Miter: 0,
23
- Round: 1,
24
- Bevel: 2,
25
- }
26
-
27
- const StrokeCap = {
28
- Butt: 0,
29
- Round: 1,
30
- Square: 2,
31
- }
32
-
33
- const PathOp = {
34
- Difference: 0, // subtract the op path from the first path
35
- Intersect: 1, // intersect the two paths
36
- Union: 2, // union (inclusive-or) the two paths
37
- XOR: 3, // exclusive-or the two paths
38
- ReverseDifference: 4, // subtract the first path from the op path
39
- }
40
-
41
- const FillType = {
42
- Winding: 0,
43
- EvenOdd: 1,
44
- InverseWinding: 2,
45
- InverseEvenOdd: 3,
46
- }
47
-
48
26
  const SvgExportFlag = {
49
27
  ConvertTextToPaths: 0x01,
50
28
  NoPrettyXML: 0x02,
51
29
  RelativePathEncoding: 0x04,
52
30
  }
53
31
 
54
- const GlobalFontsSingleton = new GlobalFonts()
55
- let FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
56
-
57
32
  // eslint-disable-next-line sonarjs/no-unused-collection
58
33
  const Fonts = []
59
34
 
60
- Object.defineProperty(GlobalFontsSingleton, 'register', {
61
- value: function register(fontData, nameAlias = '') {
62
- const result = GlobalFontsSingleton._register(fontData, nameAlias)
63
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
64
- Fonts.push(fontData)
65
- return result
66
- },
67
- configurable: false,
68
- enumerable: false,
69
- writable: false,
70
- })
71
-
72
- Object.defineProperty(GlobalFontsSingleton, 'registerFromPath', {
73
- value: function registerFromPath(path, nameAlias = '') {
74
- const result = GlobalFontsSingleton._registerFromPath(path, nameAlias)
75
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
76
- return result
77
- },
78
- configurable: false,
79
- enumerable: false,
80
- writable: false,
81
- })
82
-
83
- Object.defineProperty(GlobalFontsSingleton, 'loadFontsFromDir', {
84
- value: function loadFontsFromDir(path) {
85
- const result = GlobalFontsSingleton._loadFontsFromDir(path)
86
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
87
- return result
88
- },
89
- configurable: false,
90
- enumerable: false,
91
- writable: false,
92
- })
93
-
94
- Object.defineProperty(GlobalFontsSingleton, 'families', {
35
+ Object.defineProperty(GlobalFonts, 'families', {
95
36
  get: function () {
96
- return FamilyNamesSet
37
+ return JSON.parse(GlobalFonts.getFamilies())
97
38
  },
98
39
  })
99
40
 
100
- Object.defineProperty(GlobalFontsSingleton, 'has', {
41
+ Object.defineProperty(GlobalFonts, 'has', {
101
42
  value: function has(name) {
102
- return !!FamilyNamesSet.find(({ family }) => family === name)
43
+ return !!JSON.parse(GlobalFonts.getFamilies()).find(({ family }) => family === name)
103
44
  },
104
45
  configurable: false,
105
46
  enumerable: false,
@@ -129,27 +70,6 @@ CanvasRenderingContext2D.prototype.getImageData = function getImageData(x, y, w,
129
70
  return new ImageData(data, w, h)
130
71
  }
131
72
 
132
- Path2D.prototype.stroke = function stroke(strokeOptions = {}) {
133
- const width = typeof strokeOptions.width === 'undefined' ? 1 : strokeOptions.width
134
- const miterLimit = typeof strokeOptions.miterLimit === 'undefined' ? 4 : strokeOptions.miterLimit
135
- const join = typeof strokeOptions.join === 'undefined' ? StrokeJoin.Miter : strokeOptions.join
136
- const cap = typeof strokeOptions.cap === 'undefined' ? StrokeCap.Butt : strokeOptions.cap
137
-
138
- return this._stroke(width, miterLimit, join, cap)
139
- }
140
-
141
- Path2D.prototype.getFillTypeString = function getFillTypeString() {
142
- const fillType = this.getFillType()
143
-
144
- if (fillType === FillType.Winding) {
145
- return 'nonzero'
146
- } else if (fillType === FillType.EvenOdd) {
147
- return 'evenodd'
148
- } else {
149
- return 'nonzero' // default
150
- }
151
- }
152
-
153
73
  function createCanvas(width, height, flag) {
154
74
  const isSvgBackend = typeof flag !== 'undefined'
155
75
  const canvasElement = isSvgBackend ? new SVGCanvas(width, height) : new CanvasElement(width, height)
@@ -163,8 +83,8 @@ function createCanvas(width, height, flag) {
163
83
  ctx = ctx
164
84
  ? ctx
165
85
  : isSvgBackend
166
- ? new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton, attrs.colorSpace, flag)
167
- : new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton, attrs.colorSpace)
86
+ ? new CanvasRenderingContext2D(this.width, this.height, attrs.colorSpace, flag)
87
+ : new CanvasRenderingContext2D(this.width, this.height, attrs.colorSpace)
168
88
  createContext(ctx, this.width, this.height, attrs)
169
89
 
170
90
  // napi can not define writable: true but enumerable: false property
@@ -213,87 +133,37 @@ function createCanvas(width, height, flag) {
213
133
  toDataURLAsync: canvasToDataURLAsync,
214
134
  } = Object.getPrototypeOf(canvasElement)
215
135
 
216
- // See also: https://github.com/kornelski/cavif-rs#usage
217
- const avifDefaultQuality = 80
218
- const avifConfig = {
219
- // Quality from 1 (worst) to 100 (best), the default value is 80. The numbers have different meaning than JPEG's quality scale. Beware when comparing codecs. There is no lossless compression support.
220
- quality: avifDefaultQuality,
221
-
222
- // Calculate alphaQuality, this is consistent with cavif.
223
- // https://github.com/kornelski/cavif-rs/blob/37847b95bb81d4cf90e36b7fab2c7fbbcf95abe2/src/main.rs#L97
224
- alphaQuality: Math.min((avifDefaultQuality + 100) / 2, avifDefaultQuality + avifDefaultQuality / 4 + 2),
225
- threads: 0,
226
-
227
- // Encoding speed between 1 (best, but slowest) and 10 (fastest, but a blurry mess), the default value is 4. Speeds 1 and 2 are unbelievably slow, but make files ~3-5% smaller. Speeds 7 and above degrade compression significantly, and are not recommended.
228
- speed: 4,
229
- }
230
-
231
- canvasElement.encode = function encode(type, qualityOrConfig) {
136
+ canvasElement.encode = function encode(type, qualityOrConfig = {}) {
232
137
  if (type === 'avif') {
233
- return canvasEncode.call(
234
- this,
235
- type,
236
- JSON.stringify({
237
- ...avifConfig,
238
- ...(qualityOrConfig || {}),
239
- }),
240
- )
138
+ return canvasEncode.call(this, type, JSON.stringify(qualityOrConfig))
241
139
  }
242
140
  return canvasEncode.call(this, type, qualityOrConfig)
243
141
  }
244
142
 
245
- canvasElement.encodeSync = function encodeSync(type, qualityOrConfig) {
143
+ canvasElement.encodeSync = function encodeSync(type, qualityOrConfig = {}) {
246
144
  if (type === 'avif') {
247
- return canvasEncodeSync.call(
248
- this,
249
- type,
250
- JSON.stringify({
251
- ...avifConfig,
252
- ...(qualityOrConfig || {}),
253
- }),
254
- )
145
+ return canvasEncodeSync.call(this, type, JSON.stringify(qualityOrConfig))
255
146
  }
256
147
  return canvasEncodeSync.call(this, type, qualityOrConfig)
257
148
  }
258
149
 
259
- canvasElement.toBuffer = function toBuffer(type = 'image/png', qualityOrConfig) {
150
+ canvasElement.toBuffer = function toBuffer(type = 'image/png', qualityOrConfig = {}) {
260
151
  if (type === 'avif') {
261
- return canvasToBuffer.call(
262
- this,
263
- type,
264
- JSON.stringify({
265
- ...avifConfig,
266
- ...(qualityOrConfig || {}),
267
- }),
268
- )
152
+ return canvasToBuffer.call(this, type, JSON.stringify(qualityOrConfig))
269
153
  }
270
154
  return canvasToBuffer.call(this, type, qualityOrConfig)
271
155
  }
272
156
 
273
- canvasElement.toDataURL = function toDataURL(type = 'image/png', qualityOrConfig) {
157
+ canvasElement.toDataURL = function toDataURL(type = 'image/png', qualityOrConfig = {}) {
274
158
  if (type === 'avif') {
275
- return canvasToDataURL.call(
276
- this,
277
- type,
278
- JSON.stringify({
279
- ...avifConfig,
280
- ...(qualityOrConfig || {}),
281
- }),
282
- )
159
+ return canvasToDataURL.call(this, type, JSON.stringify(qualityOrConfig))
283
160
  }
284
161
  return canvasToDataURL.call(this, type, qualityOrConfig)
285
162
  }
286
163
 
287
- canvasElement.toDataURLAsync = function toDataURLAsync(type = 'image/png', qualityOrConfig) {
164
+ canvasElement.toDataURLAsync = function toDataURLAsync(type = 'image/png', qualityOrConfig = {}) {
288
165
  if (type === 'avif') {
289
- return canvasToDataURLAsync.call(
290
- this,
291
- type,
292
- JSON.stringify({
293
- ...avifConfig,
294
- ...(qualityOrConfig || {}),
295
- }),
296
- )
166
+ return canvasToDataURLAsync.call(this, type, JSON.stringify(qualityOrConfig))
297
167
  }
298
168
  return canvasToDataURLAsync.call(this, type, qualityOrConfig)
299
169
  }
@@ -308,29 +178,25 @@ class Canvas {
308
178
  }
309
179
 
310
180
  if (!process.env.DISABLE_SYSTEM_FONTS_LOAD) {
311
- GlobalFontsSingleton.loadSystemFonts()
181
+ GlobalFonts.loadSystemFonts()
312
182
  const platformName = platform()
313
183
  const homedirPath = homedir()
314
184
  switch (platformName) {
315
185
  case 'win32':
316
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, 'AppData', 'Local', 'Microsoft', 'Windows', 'Fonts'))
186
+ GlobalFonts.loadFontsFromDir(join(homedirPath, 'AppData', 'Local', 'Microsoft', 'Windows', 'Fonts'))
317
187
  break
318
188
  case 'darwin':
319
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, 'Library', 'Fonts'))
189
+ GlobalFonts.loadFontsFromDir(join(homedirPath, 'Library', 'Fonts'))
320
190
  break
321
191
  case 'linux':
322
- GlobalFontsSingleton.loadFontsFromDir(join('usr', 'local', 'share', 'fonts'))
323
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, '.fonts'))
192
+ GlobalFonts.loadFontsFromDir(join('usr', 'local', 'share', 'fonts'))
193
+ GlobalFonts.loadFontsFromDir(join(homedirPath, '.fonts'))
324
194
  break
325
195
  }
326
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
327
- }
328
-
329
- function convertSVGTextToPath(input) {
330
- return _convertSVGTextToPath(Buffer.isBuffer(input) ? input : Buffer.from(input), GlobalFontsSingleton)
331
196
  }
332
197
 
333
198
  module.exports = {
199
+ clearAllCache,
334
200
  Canvas,
335
201
  createCanvas,
336
202
  Path2D,
@@ -341,7 +207,7 @@ module.exports = {
341
207
  StrokeCap,
342
208
  StrokeJoin,
343
209
  SvgExportFlag,
344
- GlobalFonts: GlobalFontsSingleton,
210
+ GlobalFonts: GlobalFonts,
345
211
  convertSVGTextToPath,
346
212
  DOMPoint,
347
213
  DOMMatrix,
package/js-binding.js CHANGED
@@ -196,25 +196,35 @@ if (!nativeBinding) {
196
196
  }
197
197
 
198
198
  const {
199
+ clearAllCache,
199
200
  CanvasRenderingContext2D,
200
201
  CanvasElement,
201
202
  createContext,
202
203
  SVGCanvas,
203
- Path2D,
204
+ Path,
204
205
  ImageData,
205
206
  Image,
206
207
  CanvasPattern,
207
208
  GlobalFonts,
208
209
  convertSVGTextToPath,
210
+ PathOp,
211
+ FillType,
212
+ StrokeJoin,
213
+ StrokeCap,
209
214
  } = nativeBinding
210
215
 
216
+ module.exports.clearAllCache = clearAllCache
211
217
  module.exports.CanvasRenderingContext2D = CanvasRenderingContext2D
212
218
  module.exports.CanvasElement = CanvasElement
213
219
  module.exports.createContext = createContext
214
220
  module.exports.SVGCanvas = SVGCanvas
215
- module.exports.Path2D = Path2D
221
+ module.exports.Path2D = Path
216
222
  module.exports.ImageData = ImageData
217
223
  module.exports.Image = Image
218
224
  module.exports.CanvasPattern = CanvasPattern
219
225
  module.exports.GlobalFonts = GlobalFonts
220
226
  module.exports.convertSVGTextToPath = convertSVGTextToPath
227
+ module.exports.PathOp = PathOp
228
+ module.exports.FillType = FillType
229
+ module.exports.StrokeJoin = StrokeJoin
230
+ module.exports.StrokeCap = StrokeCap
package/load-image.js CHANGED
@@ -57,7 +57,7 @@ function makeRequest(url, resolve, reject, redirectCount, requestOptions) {
57
57
  lib.get(url, requestOptions ?? {}, (res) => {
58
58
  const shouldRedirect = REDIRECT_STATUSES.has(res.statusCode) && typeof res.headers.location === 'string'
59
59
  if (shouldRedirect && redirectCount > 0)
60
- return makeRequest(res.headers.location, resolve, reject, redirectCount - 1, requestOptions)
60
+ return makeRequest(new URL(res.headers.location), resolve, reject, redirectCount - 1, requestOptions)
61
61
  if (typeof res.statusCode === 'number' && (res.statusCode < 200 || res.statusCode >= 300)) {
62
62
  return reject(new Error(`remote source rejected with status code ${res.statusCode}`))
63
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/canvas",
3
- "version": "0.1.25",
3
+ "version": "0.1.28",
4
4
  "description": "Canvas for Node.js with skia backend",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/Brooooooklyn/canvas.git",
@@ -66,7 +66,7 @@
66
66
  "@jimp/jpeg": "^0.16.1",
67
67
  "@jimp/png": "^0.16.1",
68
68
  "@napi-rs/cli": "^2.9.0",
69
- "@octokit/rest": "^18.12.0",
69
+ "@octokit/rest": "^19.0.0",
70
70
  "@swc-node/register": "^1.5.1",
71
71
  "@types/lodash": "^4.14.182",
72
72
  "@types/node": "^17.0.35",
@@ -75,15 +75,15 @@
75
75
  "ava": "^4.2.0",
76
76
  "benny": "^3.7.1",
77
77
  "canvas": "^2.9.1",
78
- "canvaskit-wasm": "^0.34.0",
79
- "colorette": "^2.0.16",
78
+ "canvaskit-wasm": "^0.35.0",
79
+ "colorette": "^2.0.19",
80
80
  "conventional-changelog-cli": "^2.2.2",
81
81
  "echarts": "^5.3.2",
82
82
  "eslint": "^8.16.0",
83
83
  "eslint-config-prettier": "^8.5.0",
84
84
  "eslint-plugin-import": "^2.26.0",
85
85
  "eslint-plugin-prettier": "^4.0.0",
86
- "eslint-plugin-sonarjs": "^0.13.0",
86
+ "eslint-plugin-sonarjs": "^0.15.0",
87
87
  "husky": "^8.0.1",
88
88
  "lint-staged": "^13.0.0",
89
89
  "lodash": "^4.17.21",
@@ -91,7 +91,9 @@
91
91
  "pinst": "^3.0.0",
92
92
  "png.js": "^0.2.1",
93
93
  "prettier": "^2.6.2",
94
- "skia-canvas": "^0.9.29",
94
+ "pretty-bytes": "^6.0.0",
95
+ "skia-canvas": "^1.0.0",
96
+ "table": "^6.8.0",
95
97
  "typescript": "^4.7.2"
96
98
  },
97
99
  "lint-staged": {
@@ -109,6 +111,10 @@
109
111
  "extensions": [
110
112
  "ts"
111
113
  ],
114
+ "files": [
115
+ "__test__/**/*.spec.ts",
116
+ "scripts/__test__/**/*.spec.ts"
117
+ ],
112
118
  "workerThreads": false,
113
119
  "cache": false,
114
120
  "timeout": "3m",
@@ -124,16 +130,16 @@
124
130
  "singleQuote": true,
125
131
  "arrowParens": "always"
126
132
  },
127
- "packageManager": "yarn@3.2.1",
133
+ "packageManager": "yarn@3.2.2",
128
134
  "optionalDependencies": {
129
- "@napi-rs/canvas-win32-x64-msvc": "0.1.25",
130
- "@napi-rs/canvas-darwin-x64": "0.1.25",
131
- "@napi-rs/canvas-linux-x64-gnu": "0.1.25",
132
- "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.25",
133
- "@napi-rs/canvas-linux-x64-musl": "0.1.25",
134
- "@napi-rs/canvas-linux-arm64-gnu": "0.1.25",
135
- "@napi-rs/canvas-linux-arm64-musl": "0.1.25",
136
- "@napi-rs/canvas-darwin-arm64": "0.1.25",
137
- "@napi-rs/canvas-android-arm64": "0.1.25"
135
+ "@napi-rs/canvas-win32-x64-msvc": "0.1.28",
136
+ "@napi-rs/canvas-darwin-x64": "0.1.28",
137
+ "@napi-rs/canvas-linux-x64-gnu": "0.1.28",
138
+ "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.28",
139
+ "@napi-rs/canvas-linux-x64-musl": "0.1.28",
140
+ "@napi-rs/canvas-linux-arm64-gnu": "0.1.28",
141
+ "@napi-rs/canvas-linux-arm64-musl": "0.1.28",
142
+ "@napi-rs/canvas-darwin-arm64": "0.1.28",
143
+ "@napi-rs/canvas-android-arm64": "0.1.28"
138
144
  }
139
145
  }