@napi-rs/canvas 0.1.82 → 0.1.84

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/actions/workflows/CI.yaml/badge.svg)](https://github.com/Brooooooklyn/canvas/actions/workflows/CI.yaml)
4
- ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm142-hotpink)
4
+ ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm143-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
 
package/index.d.ts CHANGED
@@ -5,21 +5,21 @@ export function clearAllCache(): void
5
5
 
6
6
  interface CanvasRenderingContext2D
7
7
  extends CanvasCompositing,
8
- CanvasDrawPath,
9
- CanvasFillStrokeStyles,
10
- CanvasFilters,
11
- CanvasImageData,
12
- CanvasImageSmoothing,
13
- CanvasPath,
14
- CanvasPathDrawingStyles,
15
- CanvasRect,
16
- CanvasSettings,
17
- CanvasShadowStyles,
18
- CanvasState,
19
- CanvasText,
20
- CanvasTextDrawingStyles,
21
- CanvasTransform,
22
- CanvasPDFAnnotations {}
8
+ CanvasDrawPath,
9
+ CanvasFillStrokeStyles,
10
+ CanvasFilters,
11
+ CanvasImageData,
12
+ CanvasImageSmoothing,
13
+ CanvasPath,
14
+ CanvasPathDrawingStyles,
15
+ CanvasRect,
16
+ CanvasSettings,
17
+ CanvasShadowStyles,
18
+ CanvasState,
19
+ CanvasText,
20
+ CanvasTextDrawingStyles,
21
+ CanvasTransform,
22
+ CanvasPDFAnnotations { }
23
23
 
24
24
  interface CanvasState {
25
25
  isContextLost(): boolean
@@ -211,6 +211,7 @@ interface CanvasTextDrawingStyles {
211
211
  textBaseline: CanvasTextBaseline
212
212
  textRendering: CanvasTextRendering
213
213
  wordSpacing: string
214
+ fontVariationSettings: string
214
215
  }
215
216
 
216
217
  interface CanvasFilters {
@@ -421,7 +422,7 @@ type OmitNeverOfMatrix = OmitMatrixMethod[keyof OmitMatrixMethod]
421
422
 
422
423
  export const DOMMatrix: {
423
424
  prototype: DOMMatrix
424
- new (init?: string | number[]): DOMMatrix
425
+ new(init?: string | number[]): DOMMatrix
425
426
  fromFloat32Array(array32: Float32Array): DOMMatrix
426
427
  fromFloat64Array(array64: Float64Array): DOMMatrix
427
428
  fromMatrix(other?: DOMMatrixInit): DOMMatrix
@@ -448,7 +449,7 @@ export interface DOMRect extends DOMRectReadOnly {
448
449
 
449
450
  export const DOMRect: {
450
451
  prototype: DOMRect
451
- new (x?: number, y?: number, width?: number, height?: number): DOMRect
452
+ new(x?: number, y?: number, width?: number, height?: number): DOMRect
452
453
  fromRect(other?: DOMRectInit): DOMRect
453
454
  }
454
455
 
@@ -470,7 +471,7 @@ export interface DOMPoint extends DOMPointReadOnly {
470
471
 
471
472
  export const DOMPoint: {
472
473
  prototype: DOMPoint
473
- new (x?: number, y?: number, z?: number, w?: number): DOMPoint
474
+ new(x?: number, y?: number, z?: number, w?: number): DOMPoint
474
475
  fromPoint(other?: DOMPointInit): DOMPoint
475
476
  }
476
477
 
@@ -618,6 +619,121 @@ export interface AvifConfig {
618
619
  /** set to '4:2:0' to use chroma subsampling, default '4:4:4' */
619
620
  chromaSubsampling?: ChromaSubsampling
620
621
  }
622
+
623
+ /** GIF encoding configuration for single-frame encoding */
624
+ export interface GifConfig {
625
+ /**
626
+ * Quality for NeuQuant color quantization (1-30, lower = slower but better quality)
627
+ * @default 10
628
+ */
629
+ quality?: number
630
+ }
631
+
632
+ /** Configuration for the GIF encoder (animated GIFs) */
633
+ export interface GifEncoderConfig {
634
+ /**
635
+ * Loop count: 0 = infinite loop, positive number = finite loops
636
+ * @default 0 (infinite)
637
+ */
638
+ repeat?: number
639
+ /**
640
+ * Quality for NeuQuant color quantization (1-30, lower = slower but better quality)
641
+ * @default 10
642
+ */
643
+ quality?: number
644
+ }
645
+
646
+ /** Configuration for individual GIF frames */
647
+ export interface GifFrameConfig {
648
+ /**
649
+ * Frame delay in milliseconds
650
+ * @default 100
651
+ */
652
+ delay?: number
653
+ /** Disposal method for this frame */
654
+ disposal?: GifDisposal
655
+ /** Transparent color index (0-255), if the frame has transparency */
656
+ transparent?: number
657
+ /** X offset of this frame within the canvas */
658
+ left?: number
659
+ /** Y offset of this frame within the canvas */
660
+ top?: number
661
+ }
662
+
663
+ /** GIF frame disposal method */
664
+ export enum GifDisposal {
665
+ /** Keep the frame visible (default) */
666
+ Keep = 0,
667
+ /** Clear the frame area to the background color */
668
+ Background = 1,
669
+ /** Restore to the previous frame */
670
+ Previous = 2,
671
+ }
672
+
673
+ /**
674
+ * GIF Encoder for creating animated GIFs.
675
+ * Implements `Disposable` interface for use with the `using` keyword (ES2024).
676
+ *
677
+ * @example
678
+ * ```typescript
679
+ * // Basic usage
680
+ * const encoder = new GifEncoder(100, 100, { repeat: 0, quality: 10 });
681
+ * encoder.addFrame(rgbaData, 100, 100, { delay: 100 });
682
+ * encoder.addFrame(rgbaData2, 100, 100, { delay: 100 });
683
+ * const buffer = encoder.finish();
684
+ *
685
+ * // With `using` keyword (automatic cleanup)
686
+ * {
687
+ * using encoder = new GifEncoder(100, 100);
688
+ * encoder.addFrame(frame1, 100, 100, { delay: 100 });
689
+ * const buffer = encoder.finish();
690
+ * } // encoder automatically disposed
691
+ * ```
692
+ */
693
+ export class GifEncoder implements Disposable {
694
+ /**
695
+ * Create a new GIF encoder with the specified dimensions
696
+ * @param width - Width of the GIF canvas in pixels
697
+ * @param height - Height of the GIF canvas in pixels
698
+ * @param config - Optional encoder configuration
699
+ */
700
+ constructor(width: number, height: number, config?: GifEncoderConfig)
701
+
702
+ /** Width of the GIF canvas */
703
+ readonly width: number
704
+ /** Height of the GIF canvas */
705
+ readonly height: number
706
+ /** Number of frames added so far */
707
+ readonly frameCount: number
708
+
709
+ /**
710
+ * Add a frame from RGBA pixel data
711
+ * @param data - RGBA pixel data (must be width * height * 4 bytes)
712
+ * @param width - Width of the frame in pixels
713
+ * @param height - Height of the frame in pixels
714
+ * @param config - Optional frame configuration
715
+ */
716
+ addFrame(data: Uint8Array, width: number, height: number, config?: GifFrameConfig): void
717
+
718
+ /**
719
+ * Finish encoding and return the GIF data.
720
+ * Clears all accumulated frames after encoding.
721
+ * @throws Error if no frames have been added
722
+ */
723
+ finish(): Buffer
724
+
725
+ /**
726
+ * Dispose of the encoder, clearing all accumulated frames without encoding.
727
+ * Called automatically when using the `using` keyword.
728
+ */
729
+ dispose(): void
730
+
731
+ /**
732
+ * Symbol.dispose implementation for ES2024 Explicit Resource Management.
733
+ * Allows using `using encoder = new GifEncoder(...)` syntax.
734
+ */
735
+ [Symbol.dispose](): void
736
+ }
621
737
  /**
622
738
  * https://en.wikipedia.org/wiki/Chroma_subsampling#Types_of_sampling_and_subsampling
623
739
  * https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_concepts
@@ -675,24 +791,29 @@ export class Canvas {
675
791
  encodeSync(format: 'webp' | 'jpeg', quality?: number): Buffer
676
792
  encodeSync(format: 'png'): Buffer
677
793
  encodeSync(format: 'avif', cfg?: AvifConfig): Buffer
794
+ encodeSync(format: 'gif', quality?: number): Buffer
678
795
  encode(format: 'webp' | 'jpeg', quality?: number): Promise<Buffer>
679
796
  encode(format: 'png'): Promise<Buffer>
680
797
  encode(format: 'avif', cfg?: AvifConfig): Promise<Buffer>
798
+ encode(format: 'gif', quality?: number): Promise<Buffer>
681
799
  encodeStream(format: 'webp' | 'jpeg', quality?: number): ReadableStream<Buffer>
682
800
  encodeStream(format: 'png'): ReadableStream<Buffer>
683
801
  toBuffer(mime: 'image/png'): Buffer
684
802
  toBuffer(mime: 'image/jpeg' | 'image/webp', quality?: number): Buffer
685
803
  toBuffer(mime: 'image/avif', cfg?: AvifConfig): Buffer
804
+ toBuffer(mime: 'image/gif', quality?: number): Buffer
686
805
  // raw pixels
687
806
  data(): Buffer
688
807
  toDataURL(mime?: 'image/png'): string
689
808
  toDataURL(mime: 'image/jpeg' | 'image/webp', quality?: number): string
690
- toDataURL(mime?: 'image/jpeg' | 'image/webp' | 'image/png', quality?: number): string
809
+ toDataURL(mime: 'image/gif', quality?: number): string
810
+ toDataURL(mime?: 'image/jpeg' | 'image/webp' | 'image/png' | 'image/gif', quality?: number): string
691
811
  toDataURL(mime?: 'image/avif', cfg?: AvifConfig): string
692
812
 
693
813
  toDataURLAsync(mime?: 'image/png'): Promise<string>
694
814
  toDataURLAsync(mime: 'image/jpeg' | 'image/webp', quality?: number): Promise<string>
695
- toDataURLAsync(mime?: 'image/jpeg' | 'image/webp' | 'image/png', quality?: number): Promise<string>
815
+ toDataURLAsync(mime: 'image/gif', quality?: number): Promise<string>
816
+ toDataURLAsync(mime?: 'image/jpeg' | 'image/webp' | 'image/png' | 'image/gif', quality?: number): Promise<string>
696
817
  toDataURLAsync(mime?: 'image/avif', cfg?: AvifConfig): Promise<string>
697
818
 
698
819
  toBlob(callback: (blob: Blob | null) => void, mime?: string, quality?: number): void
@@ -708,6 +829,21 @@ export declare class FontKey {
708
829
  private readonly key: symbol
709
830
  }
710
831
 
832
+ export interface FontVariationAxis {
833
+ /** OpenType tag as a 32-bit integer (e.g., 0x77676874 for 'wght') */
834
+ tag: number
835
+ /** Current value for this axis */
836
+ value: number
837
+ /** Minimum value for this axis */
838
+ min: number
839
+ /** Maximum value for this axis */
840
+ max: number
841
+ /** Default value for this axis */
842
+ def: number
843
+ /** Whether this axis should be hidden from UI */
844
+ hidden: boolean
845
+ }
846
+
711
847
  interface IGlobalFonts {
712
848
  readonly families: { family: string; styles: { weight: number; width: string; style: string }[] }[]
713
849
  // return true if succeeded
@@ -717,6 +853,24 @@ interface IGlobalFonts {
717
853
  has(name: string): boolean
718
854
  loadFontsFromDir(path: string): number
719
855
  remove(key: FontKey): void
856
+ /**
857
+ * Get variation axes for a specific font instance
858
+ * @param familyName The font family name
859
+ * @param weight Font weight (100-900)
860
+ * @param width Font width/stretch value
861
+ * @param slant Font slant (0 = upright, 1 = italic, 2 = oblique)
862
+ * @returns Array of variation axes or empty array if not a variable font
863
+ */
864
+ getVariationAxes(familyName: string, weight: number, width: number, slant: number): FontVariationAxis[]
865
+ /**
866
+ * Check if a font has variable font capabilities
867
+ * @param familyName The font family name
868
+ * @param weight Font weight (100-900)
869
+ * @param width Font width/stretch value
870
+ * @param slant Font slant (0 = upright, 1 = italic, 2 = oblique)
871
+ * @returns true if the font is a variable font
872
+ */
873
+ hasVariations(familyName: string, weight: number, width: number, slant: number): boolean
720
874
  }
721
875
 
722
876
  export const GlobalFonts: IGlobalFonts
package/index.js CHANGED
@@ -17,12 +17,21 @@ const {
17
17
  StrokeCap,
18
18
  convertSVGTextToPath,
19
19
  PdfDocument,
20
+ GifEncoder,
21
+ GifDisposal,
20
22
  } = require('./js-binding')
21
23
 
22
24
  const { DOMPoint, DOMMatrix, DOMRect } = require('./geometry')
23
25
 
24
26
  const loadImage = require('./load-image')
25
27
 
28
+ // Add Symbol.dispose support for GifEncoder (ECMAScript 2024 Explicit Resource Management)
29
+ if (GifEncoder && typeof Symbol.dispose !== 'undefined') {
30
+ GifEncoder.prototype[Symbol.dispose] = function () {
31
+ this.dispose()
32
+ }
33
+ }
34
+
26
35
  const SvgExportFlag = {
27
36
  ConvertTextToPaths: 0x01,
28
37
  NoPrettyXML: 0x02,
@@ -178,4 +187,7 @@ module.exports = {
178
187
  CanvasElement,
179
188
  SVGCanvas,
180
189
  PDFDocument: PdfDocument,
190
+ // GIF encoding
191
+ GifEncoder,
192
+ GifDisposal,
181
193
  }
package/js-binding.js CHANGED
@@ -460,3 +460,5 @@ module.exports.PathOp = nativeBinding.PathOp
460
460
  module.exports.StrokeCap = nativeBinding.StrokeCap
461
461
  module.exports.StrokeJoin = nativeBinding.StrokeJoin
462
462
  module.exports.SvgExportFlag = nativeBinding.SvgExportFlag
463
+ module.exports.GifEncoder = nativeBinding.GifEncoder
464
+ module.exports.GifDisposal = nativeBinding.GifDisposal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/canvas",
3
- "version": "0.1.82",
3
+ "version": "0.1.84",
4
4
  "description": "Canvas for Node.js with skia backend",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -77,7 +77,7 @@
77
77
  "@jimp/png": "^0.22.12",
78
78
  "@napi-rs/cli": "^3.1.1",
79
79
  "@octokit/rest": "^22.0.0",
80
- "@oxc-node/core": "^0.0.34",
80
+ "@oxc-node/core": "^0.0.35",
81
81
  "@taplo/cli": "^0.7.0",
82
82
  "@types/lodash": "^4.17.17",
83
83
  "@types/node": "^24.0.0",
@@ -102,7 +102,7 @@
102
102
  "semver": "^7.7.2",
103
103
  "skia-canvas": "^3.0.0",
104
104
  "table": "^6.9.0",
105
- "tinybench": "^5.0.0",
105
+ "tinybench": "^6.0.0",
106
106
  "typescript": "^5.8.3"
107
107
  },
108
108
  "lint-staged": {
@@ -140,17 +140,17 @@
140
140
  "singleQuote": true,
141
141
  "arrowParens": "always"
142
142
  },
143
- "packageManager": "yarn@4.11.0",
143
+ "packageManager": "yarn@4.12.0",
144
144
  "optionalDependencies": {
145
- "@napi-rs/canvas-linux-x64-gnu": "0.1.82",
146
- "@napi-rs/canvas-darwin-x64": "0.1.82",
147
- "@napi-rs/canvas-win32-x64-msvc": "0.1.82",
148
- "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.82",
149
- "@napi-rs/canvas-linux-x64-musl": "0.1.82",
150
- "@napi-rs/canvas-linux-arm64-gnu": "0.1.82",
151
- "@napi-rs/canvas-linux-arm64-musl": "0.1.82",
152
- "@napi-rs/canvas-darwin-arm64": "0.1.82",
153
- "@napi-rs/canvas-android-arm64": "0.1.82",
154
- "@napi-rs/canvas-linux-riscv64-gnu": "0.1.82"
145
+ "@napi-rs/canvas-linux-x64-gnu": "0.1.84",
146
+ "@napi-rs/canvas-darwin-x64": "0.1.84",
147
+ "@napi-rs/canvas-win32-x64-msvc": "0.1.84",
148
+ "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.84",
149
+ "@napi-rs/canvas-linux-x64-musl": "0.1.84",
150
+ "@napi-rs/canvas-linux-arm64-gnu": "0.1.84",
151
+ "@napi-rs/canvas-linux-arm64-musl": "0.1.84",
152
+ "@napi-rs/canvas-darwin-arm64": "0.1.84",
153
+ "@napi-rs/canvas-android-arm64": "0.1.84",
154
+ "@napi-rs/canvas-linux-riscv64-gnu": "0.1.84"
155
155
  }
156
156
  }