@lexmata/micropdf 0.4.0

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 (170) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +985 -0
  3. package/binding.gyp +73 -0
  4. package/dist/annot.d.ts +458 -0
  5. package/dist/annot.d.ts.map +1 -0
  6. package/dist/annot.js +697 -0
  7. package/dist/annot.js.map +1 -0
  8. package/dist/archive.d.ts +128 -0
  9. package/dist/archive.d.ts.map +1 -0
  10. package/dist/archive.js +268 -0
  11. package/dist/archive.js.map +1 -0
  12. package/dist/buffer.d.ts +572 -0
  13. package/dist/buffer.d.ts.map +1 -0
  14. package/dist/buffer.js +971 -0
  15. package/dist/buffer.js.map +1 -0
  16. package/dist/colorspace.d.ts +287 -0
  17. package/dist/colorspace.d.ts.map +1 -0
  18. package/dist/colorspace.js +542 -0
  19. package/dist/colorspace.js.map +1 -0
  20. package/dist/context.d.ts +184 -0
  21. package/dist/context.d.ts.map +1 -0
  22. package/dist/context.js +320 -0
  23. package/dist/context.js.map +1 -0
  24. package/dist/cookie.d.ts +164 -0
  25. package/dist/cookie.d.ts.map +1 -0
  26. package/dist/cookie.js +306 -0
  27. package/dist/cookie.js.map +1 -0
  28. package/dist/device.d.ts +169 -0
  29. package/dist/device.d.ts.map +1 -0
  30. package/dist/device.js +350 -0
  31. package/dist/device.js.map +1 -0
  32. package/dist/display-list.d.ts +202 -0
  33. package/dist/display-list.d.ts.map +1 -0
  34. package/dist/display-list.js +410 -0
  35. package/dist/display-list.js.map +1 -0
  36. package/dist/document.d.ts +637 -0
  37. package/dist/document.d.ts.map +1 -0
  38. package/dist/document.js +902 -0
  39. package/dist/document.js.map +1 -0
  40. package/dist/easy.d.ts +423 -0
  41. package/dist/easy.d.ts.map +1 -0
  42. package/dist/easy.js +644 -0
  43. package/dist/easy.js.map +1 -0
  44. package/dist/enhanced.d.ts +226 -0
  45. package/dist/enhanced.d.ts.map +1 -0
  46. package/dist/enhanced.js +368 -0
  47. package/dist/enhanced.js.map +1 -0
  48. package/dist/filter.d.ts +51 -0
  49. package/dist/filter.d.ts.map +1 -0
  50. package/dist/filter.js +381 -0
  51. package/dist/filter.js.map +1 -0
  52. package/dist/font.d.ts +222 -0
  53. package/dist/font.d.ts.map +1 -0
  54. package/dist/font.js +381 -0
  55. package/dist/font.js.map +1 -0
  56. package/dist/form.d.ts +214 -0
  57. package/dist/form.d.ts.map +1 -0
  58. package/dist/form.js +497 -0
  59. package/dist/form.js.map +1 -0
  60. package/dist/geometry.d.ts +469 -0
  61. package/dist/geometry.d.ts.map +1 -0
  62. package/dist/geometry.js +780 -0
  63. package/dist/geometry.js.map +1 -0
  64. package/dist/image.d.ts +172 -0
  65. package/dist/image.d.ts.map +1 -0
  66. package/dist/image.js +348 -0
  67. package/dist/image.js.map +1 -0
  68. package/dist/index.d.ts +171 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +339 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/link.d.ts +168 -0
  73. package/dist/link.d.ts.map +1 -0
  74. package/dist/link.js +343 -0
  75. package/dist/link.js.map +1 -0
  76. package/dist/micropdf.d.ts +40 -0
  77. package/dist/micropdf.d.ts.map +1 -0
  78. package/dist/micropdf.js +45 -0
  79. package/dist/micropdf.js.map +1 -0
  80. package/dist/nanopdf.d.ts +40 -0
  81. package/dist/nanopdf.d.ts.map +1 -0
  82. package/dist/nanopdf.js +45 -0
  83. package/dist/nanopdf.js.map +1 -0
  84. package/dist/native.d.ts +242 -0
  85. package/dist/native.d.ts.map +1 -0
  86. package/dist/native.js +509 -0
  87. package/dist/native.js.map +1 -0
  88. package/dist/output.d.ts +166 -0
  89. package/dist/output.d.ts.map +1 -0
  90. package/dist/output.js +365 -0
  91. package/dist/output.js.map +1 -0
  92. package/dist/path.d.ts +420 -0
  93. package/dist/path.d.ts.map +1 -0
  94. package/dist/path.js +687 -0
  95. package/dist/path.js.map +1 -0
  96. package/dist/pdf/object.d.ts +489 -0
  97. package/dist/pdf/object.d.ts.map +1 -0
  98. package/dist/pdf/object.js +1045 -0
  99. package/dist/pdf/object.js.map +1 -0
  100. package/dist/pixmap.d.ts +315 -0
  101. package/dist/pixmap.d.ts.map +1 -0
  102. package/dist/pixmap.js +590 -0
  103. package/dist/pixmap.js.map +1 -0
  104. package/dist/profiler.d.ts +159 -0
  105. package/dist/profiler.d.ts.map +1 -0
  106. package/dist/profiler.js +380 -0
  107. package/dist/profiler.js.map +1 -0
  108. package/dist/render-options.d.ts +227 -0
  109. package/dist/render-options.d.ts.map +1 -0
  110. package/dist/render-options.js +130 -0
  111. package/dist/render-options.js.map +1 -0
  112. package/dist/resource-tracking.d.ts +332 -0
  113. package/dist/resource-tracking.d.ts.map +1 -0
  114. package/dist/resource-tracking.js +653 -0
  115. package/dist/resource-tracking.js.map +1 -0
  116. package/dist/simple.d.ts +276 -0
  117. package/dist/simple.d.ts.map +1 -0
  118. package/dist/simple.js +343 -0
  119. package/dist/simple.js.map +1 -0
  120. package/dist/stext.d.ts +290 -0
  121. package/dist/stext.d.ts.map +1 -0
  122. package/dist/stext.js +312 -0
  123. package/dist/stext.js.map +1 -0
  124. package/dist/stream.d.ts +174 -0
  125. package/dist/stream.d.ts.map +1 -0
  126. package/dist/stream.js +476 -0
  127. package/dist/stream.js.map +1 -0
  128. package/dist/text.d.ts +337 -0
  129. package/dist/text.d.ts.map +1 -0
  130. package/dist/text.js +454 -0
  131. package/dist/text.js.map +1 -0
  132. package/dist/typed-arrays.d.ts +127 -0
  133. package/dist/typed-arrays.d.ts.map +1 -0
  134. package/dist/typed-arrays.js +410 -0
  135. package/dist/typed-arrays.js.map +1 -0
  136. package/dist/types.d.ts +358 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +216 -0
  139. package/dist/types.js.map +1 -0
  140. package/native/annot.cc +557 -0
  141. package/native/buffer.cc +204 -0
  142. package/native/colorspace.cc +166 -0
  143. package/native/context.cc +84 -0
  144. package/native/cookie.cc +179 -0
  145. package/native/device.cc +179 -0
  146. package/native/display_list.cc +179 -0
  147. package/native/document.cc +268 -0
  148. package/native/enhanced.cc +70 -0
  149. package/native/font.cc +282 -0
  150. package/native/form.cc +523 -0
  151. package/native/geometry.cc +255 -0
  152. package/native/image.cc +216 -0
  153. package/native/include/micropdf/enhanced.h +38 -0
  154. package/native/include/micropdf/types.h +36 -0
  155. package/native/include/micropdf.h +106 -0
  156. package/native/include/mupdf-ffi.h +39 -0
  157. package/native/include/mupdf.h +11 -0
  158. package/native/include/mupdf_minimal.h +381 -0
  159. package/native/lib/linux-x64/libmicropdf.a +0 -0
  160. package/native/link.cc +234 -0
  161. package/native/micropdf.cc +71 -0
  162. package/native/output.cc +229 -0
  163. package/native/page.cc +572 -0
  164. package/native/path.cc +259 -0
  165. package/native/pixmap.cc +240 -0
  166. package/native/stext.cc +610 -0
  167. package/native/stream.cc +239 -0
  168. package/package.json +120 -0
  169. package/scripts/build-from-rust.js +97 -0
  170. package/scripts/install.js +184 -0
package/dist/path.js ADDED
@@ -0,0 +1,687 @@
1
+ /**
2
+ * Path - PDF path construction and vector graphics
3
+ *
4
+ * This module provides comprehensive support for creating and manipulating vector paths
5
+ * used in PDF graphics. Paths are fundamental building blocks for drawing lines, curves,
6
+ * shapes, and complex vector graphics in PDF documents.
7
+ *
8
+ * This module provides 100% API compatibility with MuPDF's path operations.
9
+ *
10
+ * @module path
11
+ * @example
12
+ * ```typescript
13
+ * import { Path, StrokeState, LineCap, LineJoin, Matrix } from 'micropdf';
14
+ *
15
+ * // Create a simple path
16
+ * const path = Path.create();
17
+ * path.moveTo(10, 10);
18
+ * path.lineTo(100, 10);
19
+ * path.lineTo(100, 100);
20
+ * path.close();
21
+ *
22
+ * // Create a rectangle
23
+ * const rect = Path.create();
24
+ * rect.rect(0, 0, 200, 100);
25
+ *
26
+ * // Create a curve
27
+ * const curve = Path.create();
28
+ * curve.moveTo(0, 0);
29
+ * curve.curveTo(50, 100, 100, 100, 150, 0);
30
+ *
31
+ * // Configure stroke
32
+ * const stroke = StrokeState.create();
33
+ * stroke.setLineWidth(2);
34
+ * stroke.setLineCap(LineCap.Round);
35
+ * stroke.setLineJoin(LineJoin.Round);
36
+ * stroke.setDash([5, 3], 0); // 5 on, 3 off
37
+ *
38
+ * // Transform path
39
+ * const matrix = Matrix.scale(2, 2);
40
+ * path.transform(matrix);
41
+ * ```
42
+ */
43
+ import { Point, Rect, Matrix } from './geometry.js';
44
+ /**
45
+ * Line cap styles determine how the ends of stroked paths are rendered.
46
+ *
47
+ * @enum {number}
48
+ * @example
49
+ * ```typescript
50
+ * const stroke = StrokeState.create();
51
+ * stroke.setLineCap(LineCap.Round); // Rounded end caps
52
+ * stroke.setStartCap(LineCap.Square); // Square start cap
53
+ * stroke.setEndCap(LineCap.Butt); // Flat end cap
54
+ * ```
55
+ */
56
+ export var LineCap;
57
+ (function (LineCap) {
58
+ /**
59
+ * Butt cap - Line ends exactly at the endpoint (no extension).
60
+ * This is the most common and default cap style.
61
+ */
62
+ LineCap[LineCap["Butt"] = 0] = "Butt";
63
+ /**
64
+ * Round cap - Line extends with a semicircular cap at the endpoint.
65
+ * The diameter equals the line width.
66
+ */
67
+ LineCap[LineCap["Round"] = 1] = "Round";
68
+ /**
69
+ * Square cap - Line extends with a square cap at the endpoint.
70
+ * The extension equals half the line width.
71
+ */
72
+ LineCap[LineCap["Square"] = 2] = "Square";
73
+ /**
74
+ * Triangle cap - Line extends with a triangular cap at the endpoint.
75
+ * Less common, used for special effects.
76
+ */
77
+ LineCap[LineCap["Triangle"] = 3] = "Triangle";
78
+ })(LineCap || (LineCap = {}));
79
+ /**
80
+ * Line join styles determine how path segments connect at corners.
81
+ *
82
+ * @enum {number}
83
+ * @example
84
+ * ```typescript
85
+ * const stroke = StrokeState.create();
86
+ * stroke.setLineJoin(LineJoin.Round); // Smooth rounded corners
87
+ * stroke.setLineJoin(LineJoin.Miter); // Sharp pointed corners
88
+ * stroke.setMiterLimit(10); // Limit miter length
89
+ * ```
90
+ */
91
+ export var LineJoin;
92
+ (function (LineJoin) {
93
+ /**
94
+ * Miter join - Extends the outer edges until they meet at a point.
95
+ * Creates sharp corners but can become very long at acute angles.
96
+ * Use miterLimit to prevent excessive extension.
97
+ */
98
+ LineJoin[LineJoin["Miter"] = 0] = "Miter";
99
+ /**
100
+ * Round join - Joins segments with a circular arc.
101
+ * Creates smooth, rounded corners with radius equal to half the line width.
102
+ */
103
+ LineJoin[LineJoin["Round"] = 1] = "Round";
104
+ /**
105
+ * Bevel join - Joins segments with a straight line across the corner.
106
+ * Creates a flat, beveled corner. Safe for all angles.
107
+ */
108
+ LineJoin[LineJoin["Bevel"] = 2] = "Bevel";
109
+ /**
110
+ * Miter XPS join - Miter join variant used in XPS documents.
111
+ * Similar to standard miter but with slightly different behavior.
112
+ */
113
+ LineJoin[LineJoin["MiterXPS"] = 3] = "MiterXPS";
114
+ })(LineJoin || (LineJoin = {}));
115
+ /**
116
+ * Type alias for line cap styles (backwards compatibility).
117
+ * @deprecated Use {@link LineCap} instead
118
+ * @type {typeof LineCap}
119
+ */
120
+ export const LineCapStyle = LineCap;
121
+ /**
122
+ * Type alias for line join styles (backwards compatibility).
123
+ * @deprecated Use {@link LineJoin} instead
124
+ * @type {typeof LineJoin}
125
+ */
126
+ export const LineJoinStyle = LineJoin;
127
+ /**
128
+ * Stroke state configuration for path rendering.
129
+ *
130
+ * StrokeState encapsulates all the properties that control how paths are stroked
131
+ * (drawn with lines). This includes line width, cap styles, join styles, miter limits,
132
+ * and dash patterns.
133
+ *
134
+ * **Reference Counting**: StrokeState uses manual reference counting. Call `keep()` to
135
+ * increment the reference count and `drop()` to decrement it.
136
+ *
137
+ * @class StrokeState
138
+ * @example
139
+ * ```typescript
140
+ * // Create default stroke state
141
+ * const stroke = StrokeState.create();
142
+ *
143
+ * // Configure stroke properties
144
+ * stroke.setLineWidth(2.5);
145
+ * stroke.setStartCap(LineCap.Round);
146
+ * stroke.setLineJoin(LineJoin.Round);
147
+ * stroke.setMiterLimit(10);
148
+ *
149
+ * // Set dash pattern: 5 units on, 3 units off
150
+ * stroke.setDash([5, 3], 0);
151
+ *
152
+ * // Clone for variations
153
+ * const thickStroke = stroke.clone();
154
+ * thickStroke.setLineWidth(5);
155
+ *
156
+ * // Clean up
157
+ * stroke.drop();
158
+ * thickStroke.drop();
159
+ * ```
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * // Create dotted line
164
+ * const dotted = StrokeState.create();
165
+ * dotted.setLineWidth(1);
166
+ * dotted.setLineCap(LineCap.Round);
167
+ * dotted.setDash([2, 2], 0); // 2 on, 2 off
168
+ *
169
+ * // Create dashed line
170
+ * const dashed = StrokeState.create();
171
+ * dashed.setLineWidth(2);
172
+ * dashed.setDash([10, 5], 0); // 10 on, 5 off
173
+ *
174
+ * // Create solid line with rounded corners
175
+ * const rounded = StrokeState.create();
176
+ * rounded.setLineWidth(3);
177
+ * rounded.setLineCap(LineCap.Round);
178
+ * rounded.setLineJoin(LineJoin.Round);
179
+ * ```
180
+ */
181
+ export class StrokeState {
182
+ _lineWidth = 1.0;
183
+ _startCap = LineCap.Butt;
184
+ _dashCap = LineCap.Butt;
185
+ _endCap = LineCap.Butt;
186
+ _lineJoin = LineJoin.Miter;
187
+ _miterLimit = 10.0;
188
+ _dashPhase = 0.0;
189
+ _dashPattern = [];
190
+ _refCount = 1;
191
+ constructor() { }
192
+ /**
193
+ * Create a new stroke state
194
+ */
195
+ static create() {
196
+ return new StrokeState();
197
+ }
198
+ /**
199
+ * Create stroke state with specific dash pattern length
200
+ */
201
+ static createWithDashLen(dashLen) {
202
+ const state = new StrokeState();
203
+ state._dashPattern = new Array(dashLen).fill(0);
204
+ return state;
205
+ }
206
+ /**
207
+ * Clone this stroke state
208
+ */
209
+ clone() {
210
+ const cloned = new StrokeState();
211
+ cloned._lineWidth = this._lineWidth;
212
+ cloned._startCap = this._startCap;
213
+ cloned._dashCap = this._dashCap;
214
+ cloned._endCap = this._endCap;
215
+ cloned._lineJoin = this._lineJoin;
216
+ cloned._miterLimit = this._miterLimit;
217
+ cloned._dashPhase = this._dashPhase;
218
+ cloned._dashPattern = [...this._dashPattern];
219
+ return cloned;
220
+ }
221
+ /**
222
+ * Keep (increment ref count)
223
+ */
224
+ keep() {
225
+ this._refCount++;
226
+ return this;
227
+ }
228
+ /**
229
+ * Drop (decrement ref count)
230
+ */
231
+ drop() {
232
+ if (this._refCount > 0) {
233
+ this._refCount--;
234
+ }
235
+ }
236
+ /**
237
+ * Unshare (make a unique copy if shared)
238
+ */
239
+ unshare() {
240
+ if (this._refCount > 1) {
241
+ this._refCount--;
242
+ return this.clone();
243
+ }
244
+ return this;
245
+ }
246
+ // ============================================================================
247
+ // Line Width
248
+ // ============================================================================
249
+ get lineWidth() {
250
+ return this._lineWidth;
251
+ }
252
+ set lineWidth(width) {
253
+ this._lineWidth = width;
254
+ }
255
+ // ============================================================================
256
+ // Line Caps
257
+ // ============================================================================
258
+ get startCap() {
259
+ return this._startCap;
260
+ }
261
+ set startCap(cap) {
262
+ this._startCap = cap;
263
+ }
264
+ get dashCap() {
265
+ return this._dashCap;
266
+ }
267
+ set dashCap(cap) {
268
+ this._dashCap = cap;
269
+ }
270
+ get endCap() {
271
+ return this._endCap;
272
+ }
273
+ set endCap(cap) {
274
+ this._endCap = cap;
275
+ }
276
+ // ============================================================================
277
+ // Line Join
278
+ // ============================================================================
279
+ get lineJoin() {
280
+ return this._lineJoin;
281
+ }
282
+ set lineJoin(join) {
283
+ this._lineJoin = join;
284
+ }
285
+ get miterLimit() {
286
+ return this._miterLimit;
287
+ }
288
+ set miterLimit(limit) {
289
+ this._miterLimit = limit;
290
+ }
291
+ // ============================================================================
292
+ // Dash Pattern
293
+ // ============================================================================
294
+ get dashPhase() {
295
+ return this._dashPhase;
296
+ }
297
+ get dashLength() {
298
+ return this._dashPattern.length;
299
+ }
300
+ getDashPattern() {
301
+ return [...this._dashPattern];
302
+ }
303
+ setDash(pattern, phase = 0) {
304
+ this._dashPattern = [...pattern];
305
+ this._dashPhase = phase;
306
+ }
307
+ /**
308
+ * Check if stroke state is valid
309
+ */
310
+ isValid() {
311
+ return this._lineWidth >= 0 && this._miterLimit >= 1 && this._dashPattern.every((v) => v >= 0);
312
+ }
313
+ }
314
+ /**
315
+ * Path command types
316
+ */
317
+ var PathCmd;
318
+ (function (PathCmd) {
319
+ PathCmd[PathCmd["MoveTo"] = 0] = "MoveTo";
320
+ PathCmd[PathCmd["LineTo"] = 1] = "LineTo";
321
+ PathCmd[PathCmd["CurveTo"] = 2] = "CurveTo";
322
+ PathCmd[PathCmd["Close"] = 3] = "Close";
323
+ PathCmd[PathCmd["QuadTo"] = 4] = "QuadTo";
324
+ PathCmd[PathCmd["RectTo"] = 5] = "RectTo";
325
+ })(PathCmd || (PathCmd = {}));
326
+ /**
327
+ * A graphics path for constructing vector shapes and drawings.
328
+ *
329
+ * Path represents a sequence of drawing commands that define vector graphics.
330
+ * Paths can contain lines, curves, rectangles, and other geometric primitives.
331
+ * They can be stroked (outlined) or filled to create visible graphics in PDFs.
332
+ *
333
+ * **Path Construction**: Paths are built using a sequence of commands:
334
+ * - `moveTo()` - Start a new subpath at a point
335
+ * - `lineTo()` - Draw a straight line to a point
336
+ * - `curveTo()` - Draw a cubic Bézier curve
337
+ * - `quadTo()` - Draw a quadratic Bézier curve
338
+ * - `rect()` - Add a rectangle
339
+ * - `closePath()` / `close()` - Close the current subpath
340
+ *
341
+ * **Reference Counting**: Paths use manual reference counting. Call `keep()` to
342
+ * increment the reference count and `drop()` to decrement it.
343
+ *
344
+ * @class Path
345
+ * @example
346
+ * ```typescript
347
+ * // Draw a triangle
348
+ * const triangle = Path.create();
349
+ * triangle.moveTo(50, 0);
350
+ * triangle.lineTo(100, 100);
351
+ * triangle.lineTo(0, 100);
352
+ * triangle.close();
353
+ *
354
+ * // Draw a rectangle
355
+ * const rect = Path.create();
356
+ * rect.rect(10, 10, 200, 100);
357
+ *
358
+ * // Draw a rounded rectangle
359
+ * const roundedRect = Path.create();
360
+ * const x = 10, y = 10, w = 200, h = 100, r = 10;
361
+ * roundedRect.moveTo(x + r, y);
362
+ * roundedRect.lineTo(x + w - r, y);
363
+ * roundedRect.curveTo(x + w, y, x + w, y, x + w, y + r);
364
+ * roundedRect.lineTo(x + w, y + h - r);
365
+ * roundedRect.curveTo(x + w, y + h, x + w, y + h, x + w - r, y + h);
366
+ * roundedRect.lineTo(x + r, y + h);
367
+ * roundedRect.curveTo(x, y + h, x, y + h, x, y + h - r);
368
+ * roundedRect.lineTo(x, y + r);
369
+ * roundedRect.curveTo(x, y, x, y, x + r, y);
370
+ * roundedRect.close();
371
+ * ```
372
+ *
373
+ * @example
374
+ * ```typescript
375
+ * // Draw a sine wave
376
+ * const wave = Path.create();
377
+ * wave.moveTo(0, 50);
378
+ * for (let x = 0; x <= 200; x += 5) {
379
+ * const y = 50 + Math.sin(x * 0.1) * 20;
380
+ * wave.lineTo(x, y);
381
+ * }
382
+ *
383
+ * // Transform the path
384
+ * const matrix = Matrix.scale(2, 2);
385
+ * wave.transform(matrix);
386
+ *
387
+ * // Check if empty
388
+ * if (!wave.isEmpty()) {
389
+ * console.log('Path has commands');
390
+ * }
391
+ *
392
+ * // Clean up
393
+ * wave.drop();
394
+ * ```
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * // Draw a circle approximation with cubic Bézier curves
399
+ * const circle = Path.create();
400
+ * const cx = 100, cy = 100, r = 50;
401
+ * const k = 0.5522847498; // 4/3 * (sqrt(2) - 1)
402
+ * const kr = r * k;
403
+ *
404
+ * circle.moveTo(cx, cy - r);
405
+ * circle.curveTo(cx + kr, cy - r, cx + r, cy - kr, cx + r, cy);
406
+ * circle.curveTo(cx + r, cy + kr, cx + kr, cy + r, cx, cy + r);
407
+ * circle.curveTo(cx - kr, cy + r, cx - r, cy + kr, cx - r, cy);
408
+ * circle.curveTo(cx - r, cy - kr, cx - kr, cy - r, cx, cy - r);
409
+ * circle.close();
410
+ * ```
411
+ */
412
+ export class Path {
413
+ _commands = [];
414
+ _currentPoint = Point.ORIGIN;
415
+ _refCount = 1;
416
+ constructor() { }
417
+ /**
418
+ * Create a new empty path
419
+ */
420
+ static create() {
421
+ return new Path();
422
+ }
423
+ /**
424
+ * Keep (increment ref count)
425
+ */
426
+ keep() {
427
+ this._refCount++;
428
+ return this;
429
+ }
430
+ /**
431
+ * Drop (decrement ref count)
432
+ */
433
+ drop() {
434
+ if (this._refCount > 0) {
435
+ this._refCount--;
436
+ }
437
+ }
438
+ /**
439
+ * Clone this path
440
+ */
441
+ clone() {
442
+ const cloned = new Path();
443
+ cloned._commands = this._commands.map((cmd) => ({
444
+ cmd: cmd.cmd,
445
+ params: [...cmd.params]
446
+ }));
447
+ cloned._currentPoint = this._currentPoint;
448
+ return cloned;
449
+ }
450
+ /**
451
+ * Get the current point
452
+ */
453
+ get currentPoint() {
454
+ return this._currentPoint;
455
+ }
456
+ /**
457
+ * Check if the path is empty
458
+ */
459
+ isEmpty() {
460
+ return this._commands.length === 0;
461
+ }
462
+ moveTo(xOrPoint, y) {
463
+ const [x, actualY] = typeof xOrPoint === 'number' ? [xOrPoint, y] : [xOrPoint.x, xOrPoint.y];
464
+ this._commands.push({ cmd: PathCmd.MoveTo, params: [x, actualY] });
465
+ this._currentPoint = new Point(x, actualY);
466
+ return this;
467
+ }
468
+ lineTo(xOrPoint, y) {
469
+ const [x, actualY] = typeof xOrPoint === 'number' ? [xOrPoint, y] : [xOrPoint.x, xOrPoint.y];
470
+ this._commands.push({ cmd: PathCmd.LineTo, params: [x, actualY] });
471
+ this._currentPoint = new Point(x, actualY);
472
+ return this;
473
+ }
474
+ /**
475
+ * Draw a cubic Bézier curve
476
+ */
477
+ curveTo(cx1, cy1, cx2, cy2, x, y) {
478
+ this._commands.push({
479
+ cmd: PathCmd.CurveTo,
480
+ params: [cx1, cy1, cx2, cy2, x, y]
481
+ });
482
+ this._currentPoint = new Point(x, y);
483
+ return this;
484
+ }
485
+ /**
486
+ * Draw a quadratic Bézier curve
487
+ */
488
+ quadTo(cx, cy, x, y) {
489
+ this._commands.push({
490
+ cmd: PathCmd.QuadTo,
491
+ params: [cx, cy, x, y]
492
+ });
493
+ this._currentPoint = new Point(x, y);
494
+ return this;
495
+ }
496
+ /**
497
+ * Close the current subpath
498
+ */
499
+ closePath() {
500
+ this._commands.push({ cmd: PathCmd.Close, params: [] });
501
+ return this;
502
+ }
503
+ /**
504
+ * Close the current subpath (alias for closePath)
505
+ */
506
+ close() {
507
+ return this.closePath();
508
+ }
509
+ /**
510
+ * Add a rectangle to the path
511
+ */
512
+ rectTo(x, y, w, h) {
513
+ this._commands.push({
514
+ cmd: PathCmd.RectTo,
515
+ params: [x, y, w, h]
516
+ });
517
+ // Rectangle starts and ends at (x, y)
518
+ this._currentPoint = new Point(x, y);
519
+ return this;
520
+ }
521
+ /**
522
+ * Add a rectangle from corners
523
+ */
524
+ rect(x1, y1, x2, y2) {
525
+ return this.rectTo(x1, y1, x2 - x1, y2 - y1);
526
+ }
527
+ // ============================================================================
528
+ // Path Operations
529
+ // ============================================================================
530
+ /**
531
+ * Get the bounding box of the path
532
+ */
533
+ getBounds() {
534
+ if (this._commands.length === 0) {
535
+ return Rect.EMPTY;
536
+ }
537
+ let minX = Infinity;
538
+ let minY = Infinity;
539
+ let maxX = -Infinity;
540
+ let maxY = -Infinity;
541
+ const updateBounds = (x, y) => {
542
+ minX = Math.min(minX, x);
543
+ minY = Math.min(minY, y);
544
+ maxX = Math.max(maxX, x);
545
+ maxY = Math.max(maxY, y);
546
+ };
547
+ for (const cmd of this._commands) {
548
+ switch (cmd.cmd) {
549
+ case PathCmd.MoveTo:
550
+ case PathCmd.LineTo:
551
+ updateBounds(cmd.params[0], cmd.params[1]);
552
+ break;
553
+ case PathCmd.CurveTo:
554
+ updateBounds(cmd.params[0], cmd.params[1]);
555
+ updateBounds(cmd.params[2], cmd.params[3]);
556
+ updateBounds(cmd.params[4], cmd.params[5]);
557
+ break;
558
+ case PathCmd.QuadTo:
559
+ updateBounds(cmd.params[0], cmd.params[1]);
560
+ updateBounds(cmd.params[2], cmd.params[3]);
561
+ break;
562
+ case PathCmd.RectTo:
563
+ updateBounds(cmd.params[0], cmd.params[1]);
564
+ updateBounds(cmd.params[0] + cmd.params[2], cmd.params[1] + cmd.params[3]);
565
+ break;
566
+ }
567
+ }
568
+ if (!isFinite(minX)) {
569
+ return Rect.EMPTY;
570
+ }
571
+ return new Rect(minX, minY, maxX, maxY);
572
+ }
573
+ /**
574
+ * Transform the path by a matrix
575
+ */
576
+ transform(matrix) {
577
+ const m = Matrix.from(matrix);
578
+ for (const cmd of this._commands) {
579
+ switch (cmd.cmd) {
580
+ case PathCmd.MoveTo:
581
+ case PathCmd.LineTo:
582
+ {
583
+ const p = m.transformPoint({ x: cmd.params[0], y: cmd.params[1] });
584
+ cmd.params[0] = p.x;
585
+ cmd.params[1] = p.y;
586
+ }
587
+ break;
588
+ case PathCmd.CurveTo:
589
+ {
590
+ const p1 = m.transformPoint({ x: cmd.params[0], y: cmd.params[1] });
591
+ const p2 = m.transformPoint({ x: cmd.params[2], y: cmd.params[3] });
592
+ const p3 = m.transformPoint({ x: cmd.params[4], y: cmd.params[5] });
593
+ cmd.params[0] = p1.x;
594
+ cmd.params[1] = p1.y;
595
+ cmd.params[2] = p2.x;
596
+ cmd.params[3] = p2.y;
597
+ cmd.params[4] = p3.x;
598
+ cmd.params[5] = p3.y;
599
+ }
600
+ break;
601
+ case PathCmd.QuadTo:
602
+ {
603
+ const p1 = m.transformPoint({ x: cmd.params[0], y: cmd.params[1] });
604
+ const p2 = m.transformPoint({ x: cmd.params[2], y: cmd.params[3] });
605
+ cmd.params[0] = p1.x;
606
+ cmd.params[1] = p1.y;
607
+ cmd.params[2] = p2.x;
608
+ cmd.params[3] = p2.y;
609
+ }
610
+ break;
611
+ case PathCmd.RectTo:
612
+ {
613
+ // Transform rectangle corners
614
+ const x1 = cmd.params[0];
615
+ const y1 = cmd.params[1];
616
+ const x2 = x1 + cmd.params[2];
617
+ const y2 = y1 + cmd.params[3];
618
+ const p1 = m.transformPoint({ x: x1, y: y1 });
619
+ const p2 = m.transformPoint({ x: x2, y: y2 });
620
+ cmd.params[0] = Math.min(p1.x, p2.x);
621
+ cmd.params[1] = Math.min(p1.y, p2.y);
622
+ cmd.params[2] = Math.abs(p2.x - p1.x);
623
+ cmd.params[3] = Math.abs(p2.y - p1.y);
624
+ }
625
+ break;
626
+ }
627
+ }
628
+ // Update current point
629
+ if (this._commands.length > 0) {
630
+ const lastCmd = this._commands[this._commands.length - 1];
631
+ if (lastCmd.cmd === PathCmd.MoveTo || lastCmd.cmd === PathCmd.LineTo) {
632
+ this._currentPoint = new Point(lastCmd.params[0], lastCmd.params[1]);
633
+ }
634
+ }
635
+ return this;
636
+ }
637
+ /**
638
+ * Walk the path commands
639
+ */
640
+ walk(walker) {
641
+ for (const cmd of this._commands) {
642
+ switch (cmd.cmd) {
643
+ case PathCmd.MoveTo:
644
+ walker.moveTo?.(cmd.params[0], cmd.params[1]);
645
+ break;
646
+ case PathCmd.LineTo:
647
+ walker.lineTo?.(cmd.params[0], cmd.params[1]);
648
+ break;
649
+ case PathCmd.CurveTo:
650
+ walker.curveTo?.(cmd.params[0], cmd.params[1], cmd.params[2], cmd.params[3], cmd.params[4], cmd.params[5]);
651
+ break;
652
+ case PathCmd.QuadTo:
653
+ walker.quadTo?.(cmd.params[0], cmd.params[1], cmd.params[2], cmd.params[3]);
654
+ break;
655
+ case PathCmd.Close:
656
+ walker.closePath?.();
657
+ break;
658
+ case PathCmd.RectTo:
659
+ walker.rectTo?.(cmd.params[0], cmd.params[1], cmd.params[2], cmd.params[3]);
660
+ break;
661
+ }
662
+ }
663
+ }
664
+ /**
665
+ * Check if path is valid
666
+ */
667
+ isValid() {
668
+ return this._commands.every((cmd) => {
669
+ return cmd.params.every((p) => isFinite(p));
670
+ });
671
+ }
672
+ /**
673
+ * Get the number of commands in the path
674
+ */
675
+ get length() {
676
+ return this._commands.length;
677
+ }
678
+ /**
679
+ * Clear all commands from the path
680
+ */
681
+ clear() {
682
+ this._commands = [];
683
+ this._currentPoint = Point.ORIGIN;
684
+ return this;
685
+ }
686
+ }
687
+ //# sourceMappingURL=path.js.map