@nmmty/lazycanvas 0.6.5 → 1.0.0-dev.4

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.
Files changed (80) hide show
  1. package/ReadMe.md +1 -1
  2. package/biome.json +41 -0
  3. package/dist/core/Interpolation.d.ts +30 -0
  4. package/dist/core/Interpolation.js +200 -0
  5. package/dist/core/Scene.d.ts +96 -0
  6. package/dist/core/Scene.js +172 -0
  7. package/dist/core/Signal.d.ts +133 -0
  8. package/dist/core/Signal.js +255 -0
  9. package/dist/core/SignalUtils.d.ts +133 -0
  10. package/dist/core/SignalUtils.js +333 -0
  11. package/dist/core/ThreadScheduler.d.ts +38 -0
  12. package/dist/core/ThreadScheduler.js +74 -0
  13. package/dist/helpers/Filters.js +1 -1
  14. package/dist/helpers/FontsList.js +18 -18
  15. package/dist/helpers/Utlis.d.ts +3 -3
  16. package/dist/helpers/Utlis.js +15 -18
  17. package/dist/helpers/index.d.ts +3 -3
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.js +10 -0
  20. package/dist/jsx-runtime.d.ts +17 -0
  21. package/dist/jsx-runtime.js +111 -0
  22. package/dist/structures/LazyCanvas.d.ts +3 -45
  23. package/dist/structures/LazyCanvas.js +11 -74
  24. package/dist/structures/components/BaseLayer.d.ts +34 -12
  25. package/dist/structures/components/BaseLayer.js +68 -35
  26. package/dist/structures/components/BezierLayer.d.ts +16 -37
  27. package/dist/structures/components/BezierLayer.js +83 -46
  28. package/dist/structures/components/{Group.d.ts → Div.d.ts} +22 -16
  29. package/dist/structures/components/{Group.js → Div.js} +38 -39
  30. package/dist/structures/components/ImageLayer.d.ts +1 -1
  31. package/dist/structures/components/ImageLayer.js +27 -26
  32. package/dist/structures/components/LineLayer.d.ts +11 -37
  33. package/dist/structures/components/LineLayer.js +42 -42
  34. package/dist/structures/components/MorphLayer.d.ts +3 -32
  35. package/dist/structures/components/MorphLayer.js +35 -47
  36. package/dist/structures/components/Path2DLayer.d.ts +4 -32
  37. package/dist/structures/components/Path2DLayer.js +28 -33
  38. package/dist/structures/components/PolygonLayer.d.ts +2 -31
  39. package/dist/structures/components/PolygonLayer.js +35 -38
  40. package/dist/structures/components/QuadraticLayer.d.ts +16 -33
  41. package/dist/structures/components/QuadraticLayer.js +80 -42
  42. package/dist/structures/components/TextLayer.d.ts +4 -33
  43. package/dist/structures/components/TextLayer.js +60 -62
  44. package/dist/structures/components/index.d.ts +10 -11
  45. package/dist/structures/components/index.js +1 -2
  46. package/dist/structures/helpers/Exporter.d.ts +13 -4
  47. package/dist/structures/helpers/Exporter.js +80 -43
  48. package/dist/structures/helpers/Font.js +1 -17
  49. package/dist/structures/helpers/Gradient.js +32 -45
  50. package/dist/structures/helpers/Link.js +2 -14
  51. package/dist/structures/helpers/Pattern.js +9 -17
  52. package/dist/structures/helpers/index.d.ts +7 -7
  53. package/dist/structures/helpers/readers/JSONReader.d.ts +4 -4
  54. package/dist/structures/helpers/readers/JSONReader.js +34 -42
  55. package/dist/structures/helpers/readers/YAMLReader.js +7 -7
  56. package/dist/structures/managers/FontsManager.js +9 -18
  57. package/dist/structures/managers/LayersManager.d.ts +18 -28
  58. package/dist/structures/managers/LayersManager.js +14 -36
  59. package/dist/structures/managers/RenderManager.d.ts +1 -15
  60. package/dist/structures/managers/RenderManager.js +17 -110
  61. package/dist/structures/managers/index.d.ts +3 -5
  62. package/dist/structures/managers/index.js +0 -2
  63. package/dist/types/enum.d.ts +1 -2
  64. package/dist/types/enum.js +1 -2
  65. package/dist/types/index.d.ts +1 -1
  66. package/dist/types/types.d.ts +232 -107
  67. package/dist/utils/APNGEncoder.d.ts +67 -0
  68. package/dist/utils/APNGEncoder.js +205 -0
  69. package/dist/utils/DrawUtils.d.ts +9 -0
  70. package/dist/utils/DrawUtils.js +42 -0
  71. package/dist/utils/LazyUtil.js +1 -2
  72. package/dist/utils/utils.d.ts +4 -7
  73. package/dist/utils/utils.js +136 -77
  74. package/package.json +60 -59
  75. package/dist/structures/components/ClearLayer.d.ts +0 -147
  76. package/dist/structures/components/ClearLayer.js +0 -158
  77. package/dist/structures/managers/AnimationManager.d.ts +0 -120
  78. package/dist/structures/managers/AnimationManager.js +0 -99
  79. package/dist/structures/managers/PluginManager.d.ts +0 -230
  80. package/dist/structures/managers/PluginManager.js +0 -182
@@ -1,107 +1,232 @@
1
- import { Gradient, Link, Pattern } from "../structures/helpers";
2
- import {
3
- MorphLayer,
4
- ImageLayer,
5
- TextLayer,
6
- BezierLayer,
7
- QuadraticLayer,
8
- LineLayer,
9
- ClearLayer,
10
- Path2DLayer,
11
- IMorphLayer,
12
- IBezierLayer,
13
- IClearLayer,
14
- IImageLayer,
15
- ITextLayer,
16
- IQuadraticLayer,
17
- ILineLayer,
18
- IPath2DLayer,
19
- IPolygonLayer,
20
- PolygonLayer
21
- } from "../structures/components";
22
- import {
23
- FontWeight,
24
- GradientType,
25
- TextAlign,
26
- TextBaseline,
27
- TextDirection,
28
- LineCap,
29
- LineJoin,
30
- Export,
31
- Centring,
32
- PatternType,
33
- LinkType,
34
- GlobalCompositeOperation,
35
- ColorSpace,
36
- } from "./enum";
37
-
38
- export type ScaleType = `link-w-${string}-${number}` | `link-h-${string}-${number}` | `link-x-${string}-${number}` | `link-y-${string}-${number}` | `${number}%` | `${number}px` | number | 'vw' | 'vh' | 'vmin' | 'vmax' | Link;
39
-
40
- export type StringColorType = `rgba(${number}, ${number}, ${number}, ${number})` | `rgb(${number}, ${number}, ${number})` | `hsl(${number}, ${number}%, ${number}%)` | `hsla(${number}, ${number}%, ${number}%, ${number})` | `#${string}` | string;
41
-
42
- export type ColorType = Gradient | Pattern | StringColorType;
43
-
44
- export type JSONLayer = IMorphLayer | IImageLayer | ITextLayer | IBezierLayer | IQuadraticLayer | ILineLayer | IClearLayer | IPath2DLayer | IPolygonLayer;
45
-
46
- export type AnyLayer = MorphLayer | ImageLayer | TextLayer | BezierLayer | QuadraticLayer | LineLayer | ClearLayer | Path2DLayer | PolygonLayer;
47
-
48
- export type AnyWeight = FontWeight | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
49
-
50
- export type AnyGradientType = GradientType | 'linear' | 'radial' | 'conic';
51
-
52
- export type AnyTextAlign = TextAlign | 'left' | 'right' | 'center' | 'start' | 'end';
53
-
54
- export type AnyTextBaseline = TextBaseline | 'top' | 'hanging' | 'middle' | 'alphabetic' | 'ideographic' | 'bottom';
55
-
56
- export type AnyTextDirection = TextDirection | 'ltr' | 'rtl' | 'inherit';
57
-
58
- export type AnyLineCap = LineCap | 'butt' | 'round' | 'square';
59
-
60
- export type AnyLineJoin = LineJoin | 'bevel' | 'round' | 'miter';
61
-
62
- export type AnyExport = Export | 'canvas' | 'ctx' | 'buffer' | 'svg' | 'png' | 'jpeg' | 'jpg' | 'gif' | 'webp' | 'yaml' | 'json';
63
-
64
- export type AnyCentring = Centring | 'start' | 'start-top' | 'start-bottom' | 'center' | 'center-top' | 'center-bottom' | 'end' | 'end-top' | 'end-bottom' | 'none';
65
-
66
- export type AnyPatternType = PatternType | 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';
67
-
68
- export type AnyLinkType = LinkType | 'width' | 'height' | 'x' | 'y';
69
-
70
- export type AnyGlobalCompositeOperation = GlobalCompositeOperation | 'source-over' | 'source-in' | 'source-out' | 'source-atop' | 'destination-over' | 'destination-in' | 'destination-out' | 'destination-atop' | 'lighter' | 'copy' | 'xor' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
71
-
72
- export type AnyColorSpace = ColorSpace | 'rgb565' | 'rgba4444' | 'rgba444';
73
-
74
- export type AnyFilter = `sepia(${number}%)` | `saturate(${number}%)` | `opacity(${number}%)` | `invert(${number}%)` | `hue-rotate(${number}deg)` | `grayscale(${number}%)` | `drop-shadow(${number}px ${number}px ${number}px ${string})` | `contrast(${number}%)` | `brightness(${number}%)` | `blur(${number}px)`;
75
-
76
- export type Point = {
77
- x: ScaleType;
78
- y: ScaleType;
79
- }
80
-
81
- export type PointNumber = {
82
- x: number;
83
- y: number;
84
- };
85
-
86
- export type Extensions = 'svg' | 'png' | 'jpeg' | 'jpg' | 'gif' | 'webp' | 'yaml' | 'json';
87
-
88
- export interface Transform {
89
- rotate: number;
90
- scale: {
91
- x: number;
92
- y: number;
93
- };
94
- translate: {
95
- x: number;
96
- y: number;
97
- };
98
- matrix: DOMMatrix2DInit;
99
- }
100
-
101
- export type RadiusCorner = 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' | 'all';
102
-
103
- export type SubStringColor = {
104
- color: StringColorType;
105
- start: number;
106
- end: number;
107
- }
1
+ import { Gradient, Link, Pattern } from "../structures/helpers";
2
+ import {
3
+ MorphLayer,
4
+ ImageLayer,
5
+ TextLayer,
6
+ BezierLayer,
7
+ QuadraticLayer,
8
+ LineLayer,
9
+ Path2DLayer,
10
+ IMorphLayer,
11
+ IBezierLayer,
12
+ IImageLayer,
13
+ ITextLayer,
14
+ IQuadraticLayer,
15
+ ILineLayer,
16
+ IPath2DLayer,
17
+ IPolygonLayer,
18
+ PolygonLayer,
19
+ } from "../structures/components";
20
+ import {
21
+ FontWeight,
22
+ GradientType,
23
+ TextAlign,
24
+ TextBaseline,
25
+ TextDirection,
26
+ LineCap,
27
+ LineJoin,
28
+ Export,
29
+ Centring,
30
+ PatternType,
31
+ LinkType,
32
+ GlobalCompositeOperation,
33
+ ColorSpace,
34
+ } from "./enum";
35
+ import {
36
+ Signal,
37
+ ThreadGenerator,
38
+ SignalOptions,
39
+ TweenConfig,
40
+ unwrap,
41
+ isSignal,
42
+ } from "../core/Signal";
43
+
44
+ // Utility type for signal-enabled values
45
+ export type Signalable<T> = T | Signal<T>;
46
+
47
+ // Re-export for convenience
48
+ export type { ThreadGenerator, SignalOptions, TweenConfig };
49
+ export { unwrap, isSignal };
50
+
51
+ // Core types with Signal support
52
+ export type ScaleType =
53
+ | `link-w-${string}-${number}`
54
+ | `link-h-${string}-${number}`
55
+ | `link-x-${string}-${number}`
56
+ | `link-y-${string}-${number}`
57
+ | `${number}%`
58
+ | `${number}px`
59
+ | number
60
+ | "vw"
61
+ | "vh"
62
+ | "vmin"
63
+ | "vmax"
64
+ | Link
65
+ | Signal<number>;
66
+
67
+ export type StringColorType =
68
+ | `rgba(${number}, ${number}, ${number}, ${number})`
69
+ | `rgb(${number}, ${number}, ${number})`
70
+ | `hsl(${number}, ${number}%, ${number}%)`
71
+ | `hsla(${number}, ${number}%, ${number}%, ${number})`
72
+ | `#${string}`
73
+ | string
74
+ | Signal<string>;
75
+
76
+ export type ColorType = Gradient | Pattern | StringColorType;
77
+
78
+ export type JSONLayer =
79
+ | IMorphLayer
80
+ | IImageLayer
81
+ | ITextLayer
82
+ | IBezierLayer
83
+ | IQuadraticLayer
84
+ | ILineLayer
85
+ | IPath2DLayer
86
+ | IPolygonLayer;
87
+
88
+ export type AnyLayer =
89
+ | MorphLayer
90
+ | ImageLayer
91
+ | TextLayer
92
+ | BezierLayer
93
+ | QuadraticLayer
94
+ | LineLayer
95
+ | Path2DLayer
96
+ | PolygonLayer;
97
+
98
+ export type AnyWeight = FontWeight | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
99
+
100
+ export type AnyGradientType = GradientType | "linear" | "radial" | "conic";
101
+
102
+ export type AnyTextAlign = TextAlign | "left" | "right" | "center" | "start" | "end";
103
+
104
+ export type AnyTextBaseline =
105
+ | TextBaseline
106
+ | "top"
107
+ | "hanging"
108
+ | "middle"
109
+ | "alphabetic"
110
+ | "ideographic"
111
+ | "bottom";
112
+
113
+ export type AnyTextDirection = TextDirection | "ltr" | "rtl" | "inherit";
114
+
115
+ export type AnyLineCap = LineCap | "butt" | "round" | "square";
116
+
117
+ export type AnyLineJoin = LineJoin | "bevel" | "round" | "miter";
118
+
119
+ export type AnyExport =
120
+ | Export
121
+ | "canvas"
122
+ | "ctx"
123
+ | "buffer"
124
+ | "svg"
125
+ | "png"
126
+ | "apng"
127
+ | "jpg"
128
+ | "webp"
129
+ | "yaml"
130
+ | "json";
131
+
132
+ export type AnyCentring =
133
+ | Centring
134
+ | "start"
135
+ | "start-top"
136
+ | "start-bottom"
137
+ | "center"
138
+ | "center-top"
139
+ | "center-bottom"
140
+ | "end"
141
+ | "end-top"
142
+ | "end-bottom"
143
+ | "none";
144
+
145
+ export type AnyPatternType = PatternType | "repeat" | "repeat-x" | "repeat-y" | "no-repeat";
146
+
147
+ export type AnyLinkType = LinkType | "width" | "height" | "x" | "y";
148
+
149
+ export type AnyGlobalCompositeOperation =
150
+ | GlobalCompositeOperation
151
+ | "source-over"
152
+ | "source-in"
153
+ | "source-out"
154
+ | "source-atop"
155
+ | "destination-over"
156
+ | "destination-in"
157
+ | "destination-out"
158
+ | "destination-atop"
159
+ | "lighter"
160
+ | "copy"
161
+ | "xor"
162
+ | "multiply"
163
+ | "screen"
164
+ | "overlay"
165
+ | "darken"
166
+ | "lighten"
167
+ | "color-dodge"
168
+ | "color-burn"
169
+ | "hard-light"
170
+ | "soft-light"
171
+ | "difference"
172
+ | "exclusion"
173
+ | "hue"
174
+ | "saturation"
175
+ | "color"
176
+ | "luminosity";
177
+
178
+ export type AnyColorSpace = ColorSpace | "rgb565" | "rgba4444" | "rgba444";
179
+
180
+ export type AnyFilter =
181
+ | `sepia(${number}%)`
182
+ | `saturate(${number}%)`
183
+ | `opacity(${number}%)`
184
+ | `invert(${number}%)`
185
+ | `hue-rotate(${number}deg)`
186
+ | `grayscale(${number}%)`
187
+ | `drop-shadow(${number}px ${number}px ${number}px ${string})`
188
+ | `contrast(${number}%)`
189
+ | `brightness(${number}%)`
190
+ | `blur(${number}px)`;
191
+
192
+ export type Point = {
193
+ x: ScaleType;
194
+ y: ScaleType;
195
+ };
196
+
197
+ export type PointNumber = {
198
+ x: number;
199
+ y: number;
200
+ };
201
+
202
+ export type Extensions = "svg" | "png" | "jpeg" | "jpg" | "gif" | "webp" | "yaml" | "json";
203
+
204
+ export interface Transform {
205
+ rotate?: number;
206
+ scale?: {
207
+ x: number;
208
+ y: number;
209
+ };
210
+ translate?: {
211
+ x: number;
212
+ y: number;
213
+ };
214
+ matrix?: DOMMatrix2DInit;
215
+ }
216
+
217
+ export type RadiusCorner = "leftTop" | "leftBottom" | "rightTop" | "rightBottom" | "all";
218
+
219
+ export type SubStringColor = {
220
+ color: StringColorType;
221
+ start: number;
222
+ end: number;
223
+ };
224
+
225
+ export type StrokeOptions = {
226
+ width: number;
227
+ cap?: CanvasLineCap;
228
+ join?: CanvasLineJoin;
229
+ dashOffset?: number;
230
+ dash?: number[];
231
+ miterLimit?: number;
232
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * APNG Encoder that works directly with Uint8ClampedArray (ImageData)
3
+ * Much faster than encoding each frame to PNG separately
4
+ */
5
+ export declare class APNGEncoder {
6
+ private frames;
7
+ private width;
8
+ private height;
9
+ private fps;
10
+ constructor(width: number, height: number, fps?: number);
11
+ /**
12
+ * Add a frame from ImageData
13
+ */
14
+ addFrame(imageData: Uint8ClampedArray): this;
15
+ addFrames(...imageDatas: Uint8ClampedArray[]): this;
16
+ /**
17
+ * Encode all frames to APNG buffer
18
+ */
19
+ encode(): Buffer;
20
+ /**
21
+ * Create IHDR chunk (image header)
22
+ */
23
+ private createIHDR;
24
+ /**
25
+ * Create acTL chunk (animation control)
26
+ */
27
+ private createACTL;
28
+ /**
29
+ * Create frame chunks (fcTL + fdAT or IDAT)
30
+ * @param frameIndex - Index of the frame (0-based)
31
+ * @param sequenceNumber - Global sequence number for fcTL/fdAT chunks
32
+ */
33
+ private createFrame;
34
+ /**
35
+ * Compress ImageData using PNG filter and zlib
36
+ */
37
+ private compressImageData;
38
+ /**
39
+ * Create IEND chunk
40
+ */
41
+ private createIEND;
42
+ /**
43
+ * Create a PNG chunk with length, type, data, and CRC
44
+ */
45
+ private createChunk;
46
+ /**
47
+ * Calculate CRC32 checksum
48
+ */
49
+ private crc32;
50
+ /**
51
+ * CRC32 lookup table
52
+ */
53
+ private crcTable;
54
+ /**
55
+ * Get number of frames
56
+ */
57
+ getFrameCount(): number;
58
+ /**
59
+ * Clear all frames
60
+ */
61
+ clear(): void;
62
+ }
63
+ export default APNGEncoder;
64
+ /**
65
+ * Helper function to create APNG from ImageData array
66
+ */
67
+ export declare function createAPNG(frames: Uint8ClampedArray[], width: number, height: number, fps?: number): Buffer;
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APNGEncoder = void 0;
4
+ exports.createAPNG = createAPNG;
5
+ const node_zlib_1 = require("node:zlib");
6
+ /**
7
+ * APNG Encoder that works directly with Uint8ClampedArray (ImageData)
8
+ * Much faster than encoding each frame to PNG separately
9
+ */
10
+ class APNGEncoder {
11
+ constructor(width, height, fps = 30) {
12
+ this.frames = [];
13
+ /**
14
+ * CRC32 lookup table
15
+ */
16
+ this.crcTable = (() => {
17
+ const table = new Uint32Array(256);
18
+ for (let i = 0; i < 256; i++) {
19
+ let c = i;
20
+ for (let k = 0; k < 8; k++) {
21
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
22
+ }
23
+ table[i] = c;
24
+ }
25
+ return table;
26
+ })();
27
+ this.width = width;
28
+ this.height = height;
29
+ this.fps = fps;
30
+ }
31
+ /**
32
+ * Add a frame from ImageData
33
+ */
34
+ addFrame(imageData) {
35
+ if (imageData.length !== this.width * this.height * 4) {
36
+ throw new Error(`Invalid ImageData size. Expected ${this.width * this.height * 4}, got ${imageData.length}`);
37
+ }
38
+ this.frames.push(imageData);
39
+ return this;
40
+ }
41
+ addFrames(...imageDatas) {
42
+ for (const imageData of imageDatas) {
43
+ this.addFrame(imageData);
44
+ }
45
+ return this;
46
+ }
47
+ /**
48
+ * Encode all frames to APNG buffer
49
+ */
50
+ encode() {
51
+ if (this.frames.length === 0) {
52
+ throw new Error("No frames to encode");
53
+ }
54
+ const chunks = [];
55
+ // PNG signature
56
+ chunks.push(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]));
57
+ // IHDR chunk
58
+ chunks.push(this.createIHDR());
59
+ // acTL chunk (animation control)
60
+ chunks.push(this.createACTL());
61
+ // Add all frames with proper sequence numbering
62
+ let sequenceNumber = 0;
63
+ for (let i = 0; i < this.frames.length; i++) {
64
+ chunks.push(...this.createFrame(i, sequenceNumber));
65
+ // First frame: fcTL (0) + IDAT = 1 chunk with sequence
66
+ // Other frames: fcTL (n) + fdAT (n+1) = 2 chunks with sequences
67
+ sequenceNumber += i === 0 ? 1 : 2;
68
+ }
69
+ // IEND chunk
70
+ chunks.push(this.createIEND());
71
+ return Buffer.concat(chunks);
72
+ }
73
+ /**
74
+ * Create IHDR chunk (image header)
75
+ */
76
+ createIHDR() {
77
+ const data = Buffer.alloc(13);
78
+ data.writeUInt32BE(this.width, 0);
79
+ data.writeUInt32BE(this.height, 4);
80
+ data[8] = 8; // bit depth
81
+ data[9] = 6; // color type: RGBA
82
+ data[10] = 0; // compression method
83
+ data[11] = 0; // filter method
84
+ data[12] = 0; // interlace method
85
+ return this.createChunk("IHDR", data);
86
+ }
87
+ /**
88
+ * Create acTL chunk (animation control)
89
+ */
90
+ createACTL() {
91
+ const data = Buffer.alloc(8);
92
+ data.writeUInt32BE(this.frames.length, 0); // num_frames
93
+ data.writeUInt32BE(0, 4); // num_plays (0 = infinite)
94
+ return this.createChunk("acTL", data);
95
+ }
96
+ /**
97
+ * Create frame chunks (fcTL + fdAT or IDAT)
98
+ * @param frameIndex - Index of the frame (0-based)
99
+ * @param sequenceNumber - Global sequence number for fcTL/fdAT chunks
100
+ */
101
+ createFrame(frameIndex, sequenceNumber) {
102
+ const chunks = [];
103
+ // fcTL chunk (frame control) - always comes first
104
+ const fctl = Buffer.alloc(26);
105
+ fctl.writeUInt32BE(sequenceNumber, 0); // sequence_number
106
+ fctl.writeUInt32BE(this.width, 4); // width
107
+ fctl.writeUInt32BE(this.height, 8); // height
108
+ fctl.writeUInt32BE(0, 12); // x_offset
109
+ fctl.writeUInt32BE(0, 16); // y_offset
110
+ // Frame delay (delay_num / delay_den seconds)
111
+ const delayNum = 1;
112
+ const delayDen = this.fps;
113
+ fctl.writeUInt16BE(delayNum, 20);
114
+ fctl.writeUInt16BE(delayDen, 22);
115
+ fctl[24] = 0; // dispose_op: APNG_DISPOSE_OP_NONE
116
+ fctl[25] = 0; // blend_op: APNG_BLEND_OP_SOURCE
117
+ chunks.push(this.createChunk("fcTL", fctl));
118
+ // Compress frame data
119
+ const imageData = this.frames[frameIndex];
120
+ const compressed = this.compressImageData(imageData);
121
+ // First frame uses IDAT (no sequence number), subsequent frames use fdAT
122
+ if (frameIndex === 0) {
123
+ chunks.push(this.createChunk("IDAT", compressed));
124
+ }
125
+ else {
126
+ // fdAT includes sequence number (sequenceNumber + 1 for the data chunk)
127
+ const fdatData = Buffer.alloc(4 + compressed.length);
128
+ fdatData.writeUInt32BE(sequenceNumber + 1, 0);
129
+ compressed.copy(fdatData, 4);
130
+ chunks.push(this.createChunk("fdAT", fdatData));
131
+ }
132
+ return chunks;
133
+ }
134
+ /**
135
+ * Compress ImageData using PNG filter and zlib
136
+ */
137
+ compressImageData(imageData) {
138
+ const bytesPerPixel = 4; // RGBA
139
+ const stride = this.width * bytesPerPixel;
140
+ const filtered = Buffer.alloc(imageData.length + this.height);
141
+ // Apply PNG filter type 0 (None) to each scanline
142
+ for (let y = 0; y < this.height; y++) {
143
+ const offset = y * stride;
144
+ const filteredOffset = y * (stride + 1);
145
+ filtered[filteredOffset] = 0; // Filter type: None
146
+ imageData.subarray(offset, offset + stride).forEach((byte, i) => {
147
+ filtered[filteredOffset + 1 + i] = byte;
148
+ });
149
+ }
150
+ // Compress with zlib
151
+ return (0, node_zlib_1.deflateSync)(filtered, { level: 6 });
152
+ }
153
+ /**
154
+ * Create IEND chunk
155
+ */
156
+ createIEND() {
157
+ return this.createChunk("IEND", Buffer.alloc(0));
158
+ }
159
+ /**
160
+ * Create a PNG chunk with length, type, data, and CRC
161
+ */
162
+ createChunk(type, data) {
163
+ const length = Buffer.alloc(4);
164
+ length.writeUInt32BE(data.length, 0);
165
+ const typeBuffer = Buffer.from(type, "ascii");
166
+ const crc = this.crc32(Buffer.concat([typeBuffer, data]));
167
+ const crcBuffer = Buffer.alloc(4);
168
+ crcBuffer.writeUInt32BE(crc, 0);
169
+ return Buffer.concat([length, typeBuffer, data, crcBuffer]);
170
+ }
171
+ /**
172
+ * Calculate CRC32 checksum
173
+ */
174
+ crc32(data) {
175
+ let crc = 0xffffffff;
176
+ for (let i = 0; i < data.length; i++) {
177
+ crc = this.crcTable[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);
178
+ }
179
+ return (crc ^ 0xffffffff) >>> 0;
180
+ }
181
+ /**
182
+ * Get number of frames
183
+ */
184
+ getFrameCount() {
185
+ return this.frames.length;
186
+ }
187
+ /**
188
+ * Clear all frames
189
+ */
190
+ clear() {
191
+ this.frames = [];
192
+ }
193
+ }
194
+ exports.APNGEncoder = APNGEncoder;
195
+ exports.default = APNGEncoder;
196
+ /**
197
+ * Helper function to create APNG from ImageData array
198
+ */
199
+ function createAPNG(frames, width, height, fps = 30) {
200
+ const encoder = new APNGEncoder(width, height, fps);
201
+ for (const frame of frames) {
202
+ encoder.addFrame(frame);
203
+ }
204
+ return encoder.encode();
205
+ }
@@ -0,0 +1,9 @@
1
+ import { SKRSContext2D } from "@napi-rs/canvas";
2
+ import { Signal } from "../core/Signal";
3
+ import { StrokeOptions } from "../types";
4
+ export declare class DrawUtils {
5
+ static drawShadow(ctx: SKRSContext2D, shadow: any): void;
6
+ static opacity(ctx: SKRSContext2D, opacity?: number | Signal<number>): void;
7
+ static filters(ctx: SKRSContext2D, filters: string | null | undefined): void;
8
+ static fillStyle(ctx: SKRSContext2D, color: string | CanvasGradient | CanvasPattern, fillStyle?: StrokeOptions): void;
9
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DrawUtils = void 0;
4
+ const Signal_1 = require("../core/Signal");
5
+ class DrawUtils {
6
+ static drawShadow(ctx, shadow) {
7
+ if (shadow) {
8
+ ctx.shadowColor = shadow.color;
9
+ ctx.shadowBlur = shadow.blur || 0;
10
+ ctx.shadowOffsetX = shadow.offsetX || 0;
11
+ ctx.shadowOffsetY = shadow.offsetY || 0;
12
+ }
13
+ }
14
+ static opacity(ctx, opacity = 1) {
15
+ const opacityValue = (0, Signal_1.unwrap)(opacity);
16
+ if (opacityValue < 1) {
17
+ ctx.globalAlpha = opacityValue;
18
+ }
19
+ }
20
+ static filters(ctx, filters) {
21
+ if (filters) {
22
+ ctx.filter = filters;
23
+ }
24
+ }
25
+ static fillStyle(ctx, color, fillStyle) {
26
+ if (fillStyle) {
27
+ ctx.lineWidth = fillStyle.width;
28
+ ctx.lineCap = fillStyle.cap || "butt";
29
+ ctx.lineJoin = fillStyle.join || "miter";
30
+ ctx.miterLimit = fillStyle.miterLimit || 10;
31
+ if (fillStyle.dash) {
32
+ ctx.setLineDash(fillStyle.dash);
33
+ ctx.lineDashOffset = fillStyle.dashOffset || 0;
34
+ }
35
+ ctx.strokeStyle = color;
36
+ }
37
+ else {
38
+ ctx.fillStyle = color;
39
+ }
40
+ }
41
+ }
42
+ exports.DrawUtils = DrawUtils;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.defaultArg = exports.LazyLog = exports.LazyError = void 0;
4
4
  class LazyError extends Error {
5
- message;
6
5
  constructor(message) {
7
6
  super(message);
8
7
  this.message = "[LazyCanvas] [ERROR] " + message;
@@ -31,5 +30,5 @@ exports.defaultArg = {
31
30
  },
32
31
  vl(vertical, layer) {
33
32
  return { vertical: vertical || false, layer: layer || false };
34
- }
33
+ },
35
34
  };