@lexmata/micropdf 0.4.0 → 0.5.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.
package/dist/enhanced.js CHANGED
@@ -1,368 +1,958 @@
1
1
  /**
2
- * Enhanced - MicroPDF high-level convenience API
2
+ * Enhanced MicroPDF Functions (mp_* prefix)
3
3
  *
4
- * This module provides MicroPDF-specific high-level functions for common PDF operations.
5
- * These are convenience wrappers that simplify complex workflows and provide a more
6
- * user-friendly API for common tasks.
7
- *
8
- * The Enhanced API includes operations like:
9
- * - Adding blank pages
10
- * - Adding watermarks
11
- * - Drawing shapes (rectangles, circles, lines)
12
- * - Merging and splitting PDFs
13
- * - Optimizing and linearizing PDFs
14
- *
15
- * @module enhanced
16
- * @example
17
- * ```typescript
18
- * import { Enhanced, Document } from 'micropdf';
19
- *
20
- * const enhanced = new Enhanced();
21
- * const doc = Document.open('document.pdf');
22
- *
23
- * // Add a blank page
24
- * enhanced.addBlankPage(doc, 612, 792); // US Letter size
25
- *
26
- * // Add a watermark
27
- * enhanced.addWatermark(
28
- * doc,
29
- * 'CONFIDENTIAL',
30
- * { x: 300, y: 400 },
31
- * 12,
32
- * 0.3 // 30% opacity
33
- * );
34
- *
35
- * // Draw shapes
36
- * enhanced.drawRectangle(
37
- * doc,
38
- * 0, // page index
39
- * { x0: 100, y0: 100, x1: 200, y1: 200 },
40
- * [255, 0, 0], // red
41
- * 0.5, // opacity
42
- * 2, // line width
43
- * true // fill
44
- * );
45
- *
46
- * // Save
47
- * doc.save('output.pdf');
48
- * doc.close();
49
- * ```
50
- *
51
- * @example
52
- * ```typescript
53
- * // Merge multiple PDFs
54
- * const enhanced = new Enhanced();
55
- * enhanced.mergePdfs(
56
- * ['doc1.pdf', 'doc2.pdf', 'doc3.pdf'],
57
- * 'merged.pdf'
58
- * );
59
- *
60
- * // Split a PDF
61
- * enhanced.splitPdf(
62
- * 'document.pdf',
63
- * 'output-dir',
64
- * { startPage: 0, endPage: 10 }
65
- * );
66
- *
67
- * // Optimize a PDF
68
- * enhanced.optimizePdf('large.pdf', 'optimized.pdf');
69
- *
70
- * // Linearize for web viewing
71
- * enhanced.linearizePdf('document.pdf', 'web-optimized.pdf');
72
- * ```
4
+ * This module provides TypeScript bindings for all 120+ enhanced MicroPDF
5
+ * functions including:
6
+ * - Print Production (N-Up, Booklet, Poster)
7
+ * - Digital Signatures & Encryption
8
+ * - HTML to PDF Conversion
9
+ * - Document Composition (Platypus-like)
10
+ * - PDF Validation & Repair
73
11
  */
74
- import { getDefaultContext } from './context.js';
75
- import { Color } from './geometry.js';
76
12
  import { native } from './native.js';
13
+ // ============================================================================
14
+ // Type Definitions
15
+ // ============================================================================
16
+ /** Page size presets */
17
+ export var PageSize;
18
+ (function (PageSize) {
19
+ PageSize[PageSize["A4"] = 0] = "A4";
20
+ PageSize[PageSize["Letter"] = 1] = "Letter";
21
+ PageSize[PageSize["Legal"] = 2] = "Legal";
22
+ PageSize[PageSize["A3"] = 3] = "A3";
23
+ PageSize[PageSize["A5"] = 4] = "A5";
24
+ PageSize[PageSize["B4"] = 5] = "B4";
25
+ PageSize[PageSize["B5"] = 6] = "B5";
26
+ PageSize[PageSize["Executive"] = 7] = "Executive";
27
+ PageSize[PageSize["Ledger"] = 8] = "Ledger";
28
+ PageSize[PageSize["Tabloid"] = 9] = "Tabloid";
29
+ })(PageSize || (PageSize = {}));
30
+ /** Binding methods for booklet creation */
31
+ export var BindingMethod;
32
+ (function (BindingMethod) {
33
+ BindingMethod[BindingMethod["SaddleStitch"] = 0] = "SaddleStitch";
34
+ BindingMethod[BindingMethod["PerfectBinding"] = 1] = "PerfectBinding";
35
+ BindingMethod[BindingMethod["SideStitch"] = 2] = "SideStitch";
36
+ BindingMethod[BindingMethod["WireO"] = 3] = "WireO";
37
+ BindingMethod[BindingMethod["CaseBinding"] = 4] = "CaseBinding";
38
+ })(BindingMethod || (BindingMethod = {}));
39
+ /** Page box types */
40
+ export var PageBoxType;
41
+ (function (PageBoxType) {
42
+ PageBoxType[PageBoxType["MediaBox"] = 0] = "MediaBox";
43
+ PageBoxType[PageBoxType["CropBox"] = 1] = "CropBox";
44
+ PageBoxType[PageBoxType["BleedBox"] = 2] = "BleedBox";
45
+ PageBoxType[PageBoxType["TrimBox"] = 3] = "TrimBox";
46
+ PageBoxType[PageBoxType["ArtBox"] = 4] = "ArtBox";
47
+ })(PageBoxType || (PageBoxType = {}));
48
+ /** Unit types for measurements */
49
+ export var Unit;
50
+ (function (Unit) {
51
+ Unit[Unit["Points"] = 0] = "Points";
52
+ Unit[Unit["Millimeters"] = 1] = "Millimeters";
53
+ Unit[Unit["Inches"] = 2] = "Inches";
54
+ Unit[Unit["Centimeters"] = 3] = "Centimeters";
55
+ })(Unit || (Unit = {}));
56
+ /** Encryption algorithms */
57
+ export var EncryptionAlgorithm;
58
+ (function (EncryptionAlgorithm) {
59
+ EncryptionAlgorithm[EncryptionAlgorithm["RC4_40"] = 0] = "RC4_40";
60
+ EncryptionAlgorithm[EncryptionAlgorithm["RC4_128"] = 1] = "RC4_128";
61
+ EncryptionAlgorithm[EncryptionAlgorithm["AES_128"] = 2] = "AES_128";
62
+ EncryptionAlgorithm[EncryptionAlgorithm["AES_256"] = 3] = "AES_256";
63
+ })(EncryptionAlgorithm || (EncryptionAlgorithm = {}));
64
+ /** Document permissions */
65
+ export var DocumentPermission;
66
+ (function (DocumentPermission) {
67
+ DocumentPermission[DocumentPermission["Print"] = 4] = "Print";
68
+ DocumentPermission[DocumentPermission["ModifyContents"] = 8] = "ModifyContents";
69
+ DocumentPermission[DocumentPermission["Copy"] = 16] = "Copy";
70
+ DocumentPermission[DocumentPermission["ModifyAnnotations"] = 32] = "ModifyAnnotations";
71
+ DocumentPermission[DocumentPermission["FillForms"] = 256] = "FillForms";
72
+ DocumentPermission[DocumentPermission["ExtractForAccessibility"] = 512] = "ExtractForAccessibility";
73
+ DocumentPermission[DocumentPermission["Assemble"] = 1024] = "Assemble";
74
+ DocumentPermission[DocumentPermission["PrintHighQuality"] = 2048] = "PrintHighQuality";
75
+ })(DocumentPermission || (DocumentPermission = {}));
76
+ /** Text alignment */
77
+ export var TextAlign;
78
+ (function (TextAlign) {
79
+ TextAlign[TextAlign["Left"] = 0] = "Left";
80
+ TextAlign[TextAlign["Center"] = 1] = "Center";
81
+ TextAlign[TextAlign["Right"] = 2] = "Right";
82
+ TextAlign[TextAlign["Justify"] = 3] = "Justify";
83
+ })(TextAlign || (TextAlign = {}));
84
+ /** Validation modes */
85
+ export var ValidationMode;
86
+ (function (ValidationMode) {
87
+ ValidationMode[ValidationMode["Quick"] = 0] = "Quick";
88
+ ValidationMode[ValidationMode["Standard"] = 1] = "Standard";
89
+ ValidationMode[ValidationMode["Strict"] = 2] = "Strict";
90
+ })(ValidationMode || (ValidationMode = {}));
91
+ // ============================================================================
92
+ // Print Production Functions
93
+ // ============================================================================
77
94
  /**
78
- * Enhanced MicroPDF API for high-level PDF operations.
79
- *
80
- * Provides convenient methods for common PDF manipulation tasks that would
81
- * otherwise require multiple lower-level API calls.
82
- *
83
- * @class Enhanced
84
- * @example
85
- * ```typescript
86
- * const enhanced = new Enhanced();
87
- * const doc = Document.open('document.pdf');
88
- *
89
- * // Add a watermark to all pages
90
- * for (let i = 0; i < doc.pageCount; i++) {
91
- * enhanced.addWatermark(
92
- * doc,
93
- * 'DRAFT',
94
- * { x: 300, y: 400 },
95
- * 48,
96
- * 0.2
97
- * );
98
- * }
99
- *
100
- * doc.save('watermarked.pdf');
101
- * doc.close();
102
- * ```
103
- */
104
- export class Enhanced {
105
- _ctx;
106
- constructor(ctx) {
107
- this._ctx = ctx || getDefaultContext();
108
- }
109
- /**
110
- * Get the context
111
- */
112
- get context() {
113
- return this._ctx;
114
- }
115
- // ============================================================================
116
- // Page Operations
117
- // ============================================================================
118
- /**
119
- * Add a blank page to a document using FFI
120
- * @returns Page number of newly added page
121
- * @throws Error when native bindings are not available
122
- */
123
- addBlankPage(_doc, width, height) {
124
- // Get native handles (will be available when Document exposes them)
125
- const ctx = this._ctx?._nativeCtx;
126
- const nativeDoc = _doc?._doc;
127
- if (!ctx || !nativeDoc) {
128
- throw new Error('Adding blank page requires native FFI bindings (mp_add_blank_page)');
129
- }
130
- return native.npAddBlankPage(ctx, nativeDoc, width, height);
131
- }
132
- // ============================================================================
133
- // Drawing Operations
134
- // ============================================================================
135
- /**
136
- * Draw a line on a page using FFI
137
- * @throws Error when native bindings are not available
138
- */
139
- drawLine(page, x0, y0, x1, y1, color, alpha = 1.0, lineWidth = 1.0) {
140
- const ctx = this._ctx?._nativeCtx;
141
- const nativePage = page?._page;
142
- if (!ctx || !nativePage) {
143
- throw new Error('Drawing line requires native FFI bindings (mp_draw_line)');
144
- }
145
- const c = Color.from(color);
146
- const colorArray = [c.r, c.g, c.b];
147
- native.npDrawLine(ctx, nativePage, x0, y0, x1, y1, colorArray, alpha, lineWidth);
148
- }
149
- /**
150
- * Draw a rectangle on a page using FFI
151
- * @throws Error when native bindings are not available
152
- */
153
- drawRectangle(page, x, y, width, height, color, alpha = 1.0, fill = false) {
154
- const ctx = this._ctx?._nativeCtx;
155
- const nativePage = page?._page;
156
- if (!ctx || !nativePage) {
157
- throw new Error('Drawing rectangle requires native FFI bindings (mp_draw_rectangle)');
158
- }
159
- const c = Color.from(color);
160
- const colorArray = [c.r, c.g, c.b];
161
- native.npDrawRectangle(ctx, nativePage, x, y, width, height, colorArray, alpha, fill);
162
- }
163
- /**
164
- * Draw a circle on a page using FFI
165
- * @throws Error when native bindings are not available
166
- */
167
- drawCircle(page, x, y, radius, color, alpha = 1.0, fill = false) {
168
- const ctx = this._ctx?._nativeCtx;
169
- const nativePage = page?._page;
170
- if (!ctx || !nativePage) {
171
- throw new Error('Drawing circle requires native FFI bindings (mp_draw_circle)');
172
- }
173
- const c = Color.from(color);
174
- const colorArray = [c.r, c.g, c.b];
175
- native.npDrawCircle(ctx, nativePage, x, y, radius, colorArray, alpha, fill);
176
- }
177
- // ============================================================================
178
- // Watermark Operations
179
- // ============================================================================
180
- /**
181
- * Add watermark to PDF using FFI
182
- * @throws Error when native bindings are not available
183
- */
184
- async addWatermark(inputPath, _outputPath, text, _x = 100, _y = 100, fontSize = 48, opacity = 0.3) {
185
- const ctx = this._ctx?._nativeCtx;
186
- if (!ctx) {
187
- throw new Error('Watermark requires native FFI bindings (mp_add_watermark)');
188
- }
189
- // Open document
190
- const doc = native.openDocumentFromPath(ctx, inputPath);
191
- native.npAddWatermark(ctx, doc, text, fontSize, opacity);
192
- native.dropDocument(ctx, doc);
193
- }
194
- // ============================================================================
195
- // PDF Manipulation
196
- // ============================================================================
197
- /**
198
- * Merge multiple PDFs into one using FFI
199
- * @throws Error when native bindings are not available
200
- */
201
- async mergePDFs(inputPaths, outputPath) {
202
- const ctx = this._ctx?._nativeCtx;
203
- if (!ctx) {
204
- throw new Error('PDF merging requires native FFI bindings (mp_merge_pdfs)');
205
- }
206
- native.npMergePDFs(ctx, inputPaths, inputPaths.length, outputPath);
207
- }
208
- /**
209
- * Split PDF into separate files using FFI
210
- * @returns Array of output file paths
211
- * @throws Error when native bindings are not available
212
- */
213
- async splitPDF(inputPath, outputDir) {
214
- const ctx = this._ctx?._nativeCtx;
215
- if (!ctx) {
216
- throw new Error('PDF splitting requires native FFI bindings (mp_split_pdf)');
217
- }
218
- return native.npSplitPDF(ctx, inputPath, outputDir);
219
- }
220
- /**
221
- * Optimize PDF (compress, remove unused objects) using FFI
222
- * @throws Error when native bindings are not available
223
- */
224
- async optimizePDF(path) {
225
- const ctx = this._ctx?._nativeCtx;
226
- if (!ctx) {
227
- throw new Error('PDF optimization requires native FFI bindings (mp_optimize_pdf)');
228
- }
229
- native.npOptimizePDF(ctx, path);
230
- }
231
- /**
232
- * Linearize PDF for fast web viewing using FFI
233
- * @throws Error when native bindings are not available
234
- */
235
- async linearizePDF(inputPath, outputPath) {
236
- const ctx = this._ctx?._nativeCtx;
237
- if (!ctx) {
238
- throw new Error('PDF linearization requires native FFI bindings (mp_linearize_pdf)');
239
- }
240
- native.npLinearizePDF(ctx, inputPath, outputPath);
241
- }
242
- /**
243
- * Write document to PDF file using FFI
244
- * @throws Error when native bindings are not available
245
- */
246
- async writePDF(doc, path) {
247
- const ctx = this._ctx?._nativeCtx;
248
- const nativeDoc = doc?._doc;
249
- if (!ctx || !nativeDoc) {
250
- throw new Error('Writing PDF requires native FFI bindings (pdf_save_document)');
251
- }
252
- native.saveDocument(ctx, nativeDoc, path);
253
- }
254
- /**
255
- * Merge multiple PDF files into a single output file
256
- *
257
- * @param inputPaths Array of PDF file paths to merge (in order)
258
- * @param outputPath Path where the merged PDF will be saved
259
- * @returns Promise that resolves to the number of pages in the merged PDF
260
- * @throws Error if any input file is invalid, not found, or merge fails
261
- * @throws Error when native bindings are not available
262
- *
263
- * @example
264
- * ```typescript
265
- * import { Enhanced } from 'micropdf';
266
- *
267
- * const enhanced = new Enhanced();
268
- * const pageCount = await enhanced.mergePDF(
269
- * ['document1.pdf', 'document2.pdf', 'document3.pdf'],
270
- * 'merged.pdf'
271
- * );
272
- * console.log(`Merged ${pageCount} pages`);
273
- * ```
274
- *
275
- * @example Large document handling
276
- * ```typescript
277
- * // Works with large documents (5000+ pages)
278
- * const pageCount = await enhanced.mergePDF(
279
- * ['large_doc1.pdf', 'large_doc2.pdf'],
280
- * 'combined.pdf'
281
- * );
282
- * ```
283
- */
284
- async mergePDF(inputPaths, outputPath) {
285
- const ctx = this._ctx?._nativeCtx;
286
- if (!ctx) {
287
- throw new Error('Merging PDFs requires native FFI bindings (mp_merge_pdfs)');
288
- }
289
- if (!inputPaths || inputPaths.length === 0) {
290
- throw new Error('At least one input PDF path is required');
291
- }
292
- if (!outputPath) {
293
- throw new Error('Output path is required');
294
- }
295
- try {
296
- const pageCount = native.npMergePDFs(ctx, inputPaths, inputPaths.length, outputPath);
297
- if (pageCount < 0) {
298
- throw new Error('PDF merge failed');
299
- }
300
- return pageCount;
301
- }
302
- catch (error) {
303
- if (error instanceof Error) {
304
- throw new Error(`Failed to merge PDFs: ${error.message}`);
305
- }
306
- throw new Error('Failed to merge PDFs: Unknown error');
307
- }
308
- }
309
- // ============================================================================
310
- // Convenience Factory Methods
311
- // ============================================================================
312
- /**
313
- * Create a new blank PDF document
314
- * @param width Page width in points (default A4 width: 595)
315
- * @param height Page height in points (default A4 height: 842)
316
- * @throws Error This is a static method that requires instance context
317
- */
318
- static createBlankDocument(_width = 595, _height = 842) {
319
- throw new Error('Document creation requires native FFI bindings (fz_new_document). ' +
320
- 'Use Document.fromBuffer() or Enhanced instance methods instead.');
321
- }
322
- /**
323
- * Quick create PDF with text
324
- * @throws Error This is a static method that requires instance context
325
- */
326
- static async createTextPDF(_text, _outputPath, _options) {
327
- throw new Error('PDF text creation requires native FFI bindings (fz_new_document, fz_show_string). ' +
328
- 'Use Enhanced instance methods instead.');
329
- }
330
- }
331
- /**
332
- * Global enhanced API instance
333
- */
334
- let globalEnhanced = null;
335
- /**
336
- * Get global enhanced API
337
- */
338
- export function getEnhanced() {
339
- if (!globalEnhanced) {
340
- globalEnhanced = new Enhanced();
341
- }
342
- return globalEnhanced;
343
- }
344
- /**
345
- * Convenience functions (use global instance)
346
- */
347
- export async function addWatermark(inputPath, outputPath, text, x, y, fontSize, opacity) {
348
- return getEnhanced().addWatermark(inputPath, outputPath, text, x, y, fontSize, opacity);
349
- }
350
- export async function mergePDFs(inputPaths, outputPath) {
351
- return getEnhanced().mergePDFs(inputPaths, outputPath);
352
- }
353
- export async function splitPDF(inputPath, outputDir) {
354
- return getEnhanced().splitPDF(inputPath, outputDir);
355
- }
356
- export async function optimizePDF(path) {
357
- return getEnhanced().optimizePDF(path);
358
- }
359
- export async function linearizePDF(inputPath, outputPath) {
360
- return getEnhanced().linearizePDF(inputPath, outputPath);
361
- }
362
- export function createBlankDocument(width, height) {
363
- return Enhanced.createBlankDocument(width, height);
364
- }
365
- export async function createTextPDF(text, outputPath, options) {
366
- return Enhanced.createTextPDF(text, outputPath, options);
95
+ * Create a 2-up layout (2 pages per sheet)
96
+ */
97
+ export function create2Up(inputPath, outputPath, pageSize = PageSize.A4) {
98
+ const result = native.mp_create_2up?.(inputPath, outputPath, pageSize);
99
+ if (result !== 0) {
100
+ throw new Error('Failed to create 2-up layout');
101
+ }
102
+ }
103
+ /**
104
+ * Create a 4-up layout (4 pages per sheet)
105
+ */
106
+ export function create4Up(inputPath, outputPath, pageSize = PageSize.A4) {
107
+ const result = native.mp_create_4up?.(inputPath, outputPath, pageSize);
108
+ if (result !== 0) {
109
+ throw new Error('Failed to create 4-up layout');
110
+ }
111
+ }
112
+ /**
113
+ * Create a 9-up layout (9 pages per sheet)
114
+ */
115
+ export function create9Up(inputPath, outputPath, pageSize = PageSize.A4) {
116
+ const result = native.mp_create_9up?.(inputPath, outputPath, pageSize);
117
+ if (result !== 0) {
118
+ throw new Error('Failed to create 9-up layout');
119
+ }
120
+ }
121
+ /**
122
+ * Create a custom N-up layout
123
+ */
124
+ export function createNup(inputPath, outputPath, cols, rows, pageSize = PageSize.A4) {
125
+ const result = native.mp_create_nup?.(inputPath, outputPath, cols, rows, pageSize);
126
+ if (result !== 0) {
127
+ throw new Error('Failed to create N-up layout');
128
+ }
129
+ }
130
+ /**
131
+ * Create a booklet for printing
132
+ */
133
+ export function createBooklet(inputPath, outputPath, bindingType = BindingMethod.SaddleStitch, pageSize = PageSize.A4, addBlanks = true) {
134
+ const result = native.mp_create_booklet?.(inputPath, outputPath, bindingType, pageSize, addBlanks ? 1 : 0);
135
+ if (result !== 0) {
136
+ throw new Error('Failed to create booklet');
137
+ }
138
+ }
139
+ /**
140
+ * Create a saddle-stitch booklet (simplified)
141
+ */
142
+ export function createSaddleStitchBooklet(inputPath, outputPath) {
143
+ const result = native.mp_create_saddle_stitch_booklet?.(inputPath, outputPath);
144
+ if (result !== 0) {
145
+ throw new Error('Failed to create saddle-stitch booklet');
146
+ }
147
+ }
148
+ /**
149
+ * Create a poster by tiling pages
150
+ */
151
+ export function createPoster(inputPath, outputPath, tileSize, overlapMm = 10, cutMarks = true) {
152
+ const result = native.mp_create_poster?.(inputPath, outputPath, tileSize, overlapMm, cutMarks ? 1 : 0);
153
+ if (result !== 0) {
154
+ throw new Error('Failed to create poster');
155
+ }
156
+ }
157
+ /**
158
+ * Get the number of tiles for a poster
159
+ */
160
+ export function getPosterTileCount(pdfPath, tileSize, overlapMm = 10) {
161
+ return native.mp_poster_tile_count?.(pdfPath, tileSize, overlapMm) ?? 0;
162
+ }
163
+ // ============================================================================
164
+ // Page Box Management
165
+ // ============================================================================
166
+ /**
167
+ * Create a page box manager for a PDF
168
+ */
169
+ export function createPageBoxManager(pdfPath) {
170
+ const handle = native.mp_page_box_manager_create?.(pdfPath);
171
+ if (!handle || handle === 0) {
172
+ throw new Error('Failed to create page box manager');
173
+ }
174
+ return { _handle: handle };
175
+ }
176
+ /**
177
+ * Free a page box manager
178
+ */
179
+ export function freePageBoxManager(manager) {
180
+ native.mp_page_box_manager_free?.(manager._handle);
181
+ }
182
+ /**
183
+ * Get the page count from a page box manager
184
+ */
185
+ export function getPageBoxPageCount(manager) {
186
+ return native.mp_page_box_manager_page_count?.(manager._handle) ?? 0;
187
+ }
188
+ /**
189
+ * Get a page box
190
+ */
191
+ export function getPageBox(manager, page, boxType) {
192
+ const rect = { llx: 0, lly: 0, urx: 0, ury: 0 };
193
+ const result = native.mp_page_box_get?.(manager._handle, page, boxType, rect);
194
+ if (result !== 0) {
195
+ throw new Error('Failed to get page box');
196
+ }
197
+ return rect;
198
+ }
199
+ /**
200
+ * Set a page box
201
+ */
202
+ export function setPageBox(manager, page, boxType, rect) {
203
+ const result = native.mp_page_box_set?.(manager._handle, page, boxType, rect.llx, rect.lly, rect.urx, rect.ury);
204
+ if (result !== 0) {
205
+ throw new Error('Failed to set page box');
206
+ }
207
+ }
208
+ /**
209
+ * Add bleed to all pages
210
+ */
211
+ export function addBleed(manager, bleed, unit = Unit.Points) {
212
+ const result = native.mp_page_box_add_bleed?.(manager._handle, bleed, unit);
213
+ if (result !== 0) {
214
+ throw new Error('Failed to add bleed');
215
+ }
216
+ }
217
+ /**
218
+ * Save page box changes
219
+ */
220
+ export function savePageBox(manager, outputPath) {
221
+ const result = native.mp_page_box_save?.(manager._handle, outputPath);
222
+ if (result !== 0) {
223
+ throw new Error('Failed to save page boxes');
224
+ }
225
+ }
226
+ // ============================================================================
227
+ // Encryption & Decryption
228
+ // ============================================================================
229
+ /**
230
+ * Check if a PDF is encrypted
231
+ */
232
+ export function isEncrypted(pdfPath) {
233
+ return native.mp_is_encrypted?.(pdfPath) === 1;
234
+ }
235
+ /**
236
+ * Create encryption options
237
+ */
238
+ export function createEncryptionOptions() {
239
+ const handle = native.mp_encryption_options_new?.();
240
+ if (!handle || handle === 0) {
241
+ throw new Error('Failed to create encryption options');
242
+ }
243
+ return { _handle: handle };
244
+ }
245
+ /**
246
+ * Free encryption options
247
+ */
248
+ export function freeEncryptionOptions(options) {
249
+ native.mp_encryption_options_drop?.(options._handle);
250
+ }
251
+ /**
252
+ * Set user password for encryption
253
+ */
254
+ export function setUserPassword(options, password) {
255
+ native.mp_encryption_set_user_password?.(options._handle, password);
256
+ }
257
+ /**
258
+ * Set owner password for encryption
259
+ */
260
+ export function setOwnerPassword(options, password) {
261
+ native.mp_encryption_set_owner_password?.(options._handle, password);
262
+ }
263
+ /**
264
+ * Set document permissions
265
+ */
266
+ export function setPermissions(options, permissions) {
267
+ native.mp_encryption_set_permissions?.(options._handle, permissions);
268
+ }
269
+ /**
270
+ * Set encryption algorithm
271
+ */
272
+ export function setAlgorithm(options, algorithm) {
273
+ native.mp_encryption_set_algorithm?.(options._handle, algorithm);
274
+ }
275
+ /**
276
+ * Encrypt a PDF
277
+ */
278
+ export function encryptPdf(inputPath, outputPath, options) {
279
+ const result = native.mp_encrypt_pdf?.(inputPath, outputPath, options._handle);
280
+ if (result !== 0) {
281
+ throw new Error('Failed to encrypt PDF');
282
+ }
283
+ }
284
+ /**
285
+ * Decrypt a PDF
286
+ */
287
+ export function decryptPdf(inputPath, outputPath, password) {
288
+ const result = native.mp_decrypt_pdf?.(inputPath, outputPath, password);
289
+ if (result !== 0) {
290
+ throw new Error('Failed to decrypt PDF');
291
+ }
292
+ }
293
+ // ============================================================================
294
+ // Digital Signatures
295
+ // ============================================================================
296
+ /**
297
+ * Load a certificate from PEM files
298
+ */
299
+ export function loadCertificatePem(certPath, keyPath, keyPassword) {
300
+ const handle = native.mp_certificate_load_pem?.(certPath, keyPath, keyPassword ?? null);
301
+ if (!handle || handle === 0) {
302
+ throw new Error('Failed to load certificate from PEM');
303
+ }
304
+ return { _handle: handle };
305
+ }
306
+ /**
307
+ * Load a certificate from PKCS#12 file
308
+ */
309
+ export function loadCertificatePkcs12(path, password) {
310
+ const handle = native.mp_certificate_load_pkcs12?.(path, password);
311
+ if (!handle || handle === 0) {
312
+ throw new Error('Failed to load certificate from PKCS#12');
313
+ }
314
+ return { _handle: handle };
315
+ }
316
+ /**
317
+ * Free a certificate
318
+ */
319
+ export function freeCertificate(cert) {
320
+ native.mp_certificate_drop?.(cert._handle);
321
+ }
322
+ /**
323
+ * Check if a certificate is valid
324
+ */
325
+ export function isCertificateValid(cert) {
326
+ return native.mp_certificate_is_valid?.(cert._handle) === 1;
327
+ }
328
+ /**
329
+ * Get certificate subject
330
+ */
331
+ export function getCertificateSubject(cert) {
332
+ return native.mp_certificate_get_subject?.(cert._handle) ?? '';
333
+ }
334
+ /**
335
+ * Get certificate issuer
336
+ */
337
+ export function getCertificateIssuer(cert) {
338
+ return native.mp_certificate_get_issuer?.(cert._handle) ?? '';
339
+ }
340
+ /**
341
+ * Create a digital signature with appearance
342
+ */
343
+ export function createSignature(inputPath, outputPath, cert, fieldName, page, x, y, width, height, reason, location) {
344
+ const result = native.mp_signature_create?.(inputPath, outputPath, cert._handle, fieldName, page, x, y, width, height, reason ?? null, location ?? null);
345
+ if (result !== 0) {
346
+ throw new Error('Failed to create signature');
347
+ }
348
+ }
349
+ /**
350
+ * Create an invisible digital signature
351
+ */
352
+ export function createInvisibleSignature(inputPath, outputPath, cert, fieldName, reason, location) {
353
+ const result = native.mp_signature_create_invisible?.(inputPath, outputPath, cert._handle, fieldName, reason ?? null, location ?? null);
354
+ if (result !== 0) {
355
+ throw new Error('Failed to create invisible signature');
356
+ }
357
+ }
358
+ /**
359
+ * Verify a signature
360
+ */
361
+ export function verifySignature(pdfPath, fieldName) {
362
+ const result = {
363
+ valid: false,
364
+ modifiedAfterSigning: false
365
+ };
366
+ const status = native.mp_signature_verify?.(pdfPath, fieldName, result);
367
+ if (status !== 0) {
368
+ throw new Error('Failed to verify signature');
369
+ }
370
+ return result;
371
+ }
372
+ /**
373
+ * Count signatures in a PDF
374
+ */
375
+ export function countSignatures(pdfPath) {
376
+ return native.mp_signature_count?.(pdfPath) ?? 0;
377
+ }
378
+ // ============================================================================
379
+ // HTML to PDF Conversion
380
+ // ============================================================================
381
+ /**
382
+ * Create HTML conversion options
383
+ */
384
+ export function createHtmlOptions() {
385
+ const handle = native.mp_html_options_create?.();
386
+ if (!handle || handle === 0) {
387
+ throw new Error('Failed to create HTML options');
388
+ }
389
+ return { _handle: handle };
390
+ }
391
+ /**
392
+ * Free HTML options
393
+ */
394
+ export function freeHtmlOptions(options) {
395
+ native.mp_html_options_free?.(options._handle);
396
+ }
397
+ /**
398
+ * Set page size for HTML conversion
399
+ */
400
+ export function setHtmlPageSize(options, pageSize) {
401
+ native.mp_html_options_set_page_size?.(options._handle, pageSize);
402
+ }
403
+ /**
404
+ * Set custom page size for HTML conversion
405
+ */
406
+ export function setHtmlCustomPageSize(options, width, height) {
407
+ native.mp_html_options_set_page_size_custom?.(options._handle, width, height);
408
+ }
409
+ /**
410
+ * Set margins for HTML conversion
411
+ */
412
+ export function setHtmlMargins(options, top, right, bottom, left) {
413
+ native.mp_html_options_set_margins?.(options._handle, top, right, bottom, left);
414
+ }
415
+ /**
416
+ * Set landscape mode for HTML conversion
417
+ */
418
+ export function setHtmlLandscape(options, landscape) {
419
+ native.mp_html_options_set_landscape?.(options._handle, landscape ? 1 : 0);
420
+ }
421
+ /**
422
+ * Set scale for HTML conversion
423
+ */
424
+ export function setHtmlScale(options, scale) {
425
+ native.mp_html_options_set_scale?.(options._handle, scale);
426
+ }
427
+ /**
428
+ * Set print background for HTML conversion
429
+ */
430
+ export function setHtmlPrintBackground(options, enabled) {
431
+ native.mp_html_options_set_print_background?.(options._handle, enabled ? 1 : 0);
432
+ }
433
+ /**
434
+ * Set header HTML
435
+ */
436
+ export function setHtmlHeader(options, html) {
437
+ native.mp_html_options_set_header?.(options._handle, html);
438
+ }
439
+ /**
440
+ * Set footer HTML
441
+ */
442
+ export function setHtmlFooter(options, html) {
443
+ native.mp_html_options_set_footer?.(options._handle, html);
444
+ }
445
+ /**
446
+ * Enable/disable JavaScript
447
+ */
448
+ export function setHtmlJavaScript(options, enabled) {
449
+ native.mp_html_options_set_javascript?.(options._handle, enabled ? 1 : 0);
450
+ }
451
+ /**
452
+ * Set base URL for relative paths
453
+ */
454
+ export function setHtmlBaseUrl(options, url) {
455
+ native.mp_html_options_set_base_url?.(options._handle, url);
456
+ }
457
+ /**
458
+ * Set custom stylesheet
459
+ */
460
+ export function setHtmlStylesheet(options, css) {
461
+ native.mp_html_options_set_stylesheet?.(options._handle, css);
462
+ }
463
+ /**
464
+ * Convert HTML string to PDF
465
+ */
466
+ export function htmlToPdf(html, outputPath, options) {
467
+ const result = native.mp_html_to_pdf?.(html, outputPath, options?._handle ?? 0);
468
+ if (result !== 0) {
469
+ throw new Error('Failed to convert HTML to PDF');
470
+ }
471
+ }
472
+ /**
473
+ * Convert HTML file to PDF
474
+ */
475
+ export function htmlFileToPdf(htmlPath, outputPath, options) {
476
+ const result = native.mp_html_file_to_pdf?.(htmlPath, outputPath, options?._handle ?? 0);
477
+ if (result !== 0) {
478
+ throw new Error('Failed to convert HTML file to PDF');
479
+ }
480
+ }
481
+ // ============================================================================
482
+ // Document Composition (Platypus-like)
483
+ // ============================================================================
484
+ /**
485
+ * Create a document template
486
+ */
487
+ export function createDocTemplate(filename) {
488
+ const handle = native.mp_doc_template_create?.(filename);
489
+ if (!handle || handle === 0) {
490
+ throw new Error('Failed to create document template');
491
+ }
492
+ return { _handle: handle };
493
+ }
494
+ /**
495
+ * Free a document template
496
+ */
497
+ export function freeDocTemplate(template) {
498
+ native.mp_doc_template_free?.(template._handle);
499
+ }
500
+ /**
501
+ * Set page size for document template
502
+ */
503
+ export function setDocTemplatePageSize(template, width, height) {
504
+ native.mp_doc_template_set_page_size?.(template._handle, width, height);
505
+ }
506
+ /**
507
+ * Set margins for document template
508
+ */
509
+ export function setDocTemplateMargins(template, left, right, top, bottom) {
510
+ native.mp_doc_template_set_margins?.(template._handle, left, right, top, bottom);
511
+ }
512
+ /**
513
+ * Create a frame
514
+ */
515
+ export function createFrame(id, x, y, width, height) {
516
+ const handle = native.mp_frame_create?.(id, x, y, width, height);
517
+ if (!handle || handle === 0) {
518
+ throw new Error('Failed to create frame');
519
+ }
520
+ return { _handle: handle };
521
+ }
522
+ /**
523
+ * Free a frame
524
+ */
525
+ export function freeFrame(frame) {
526
+ native.mp_frame_free?.(frame._handle);
527
+ }
528
+ /**
529
+ * Get frame available width
530
+ */
531
+ export function getFrameAvailableWidth(frame) {
532
+ return native.mp_frame_available_width?.(frame._handle) ?? 0;
533
+ }
534
+ /**
535
+ * Get frame available height
536
+ */
537
+ export function getFrameAvailableHeight(frame) {
538
+ return native.mp_frame_available_height?.(frame._handle) ?? 0;
539
+ }
540
+ /**
541
+ * Create a paragraph
542
+ */
543
+ export function createParagraph(text) {
544
+ const handle = native.mp_paragraph_create?.(text);
545
+ if (!handle || handle === 0) {
546
+ throw new Error('Failed to create paragraph');
547
+ }
548
+ return { _handle: handle };
549
+ }
550
+ /**
551
+ * Free a paragraph
552
+ */
553
+ export function freeParagraph(paragraph) {
554
+ native.mp_paragraph_free?.(paragraph._handle);
555
+ }
556
+ /**
557
+ * Set paragraph font size
558
+ */
559
+ export function setParagraphFontSize(paragraph, size) {
560
+ native.mp_paragraph_set_font_size?.(paragraph._handle, size);
561
+ }
562
+ /**
563
+ * Set paragraph leading
564
+ */
565
+ export function setParagraphLeading(paragraph, leading) {
566
+ native.mp_paragraph_set_leading?.(paragraph._handle, leading);
567
+ }
568
+ /**
569
+ * Create a paragraph style
570
+ */
571
+ export function createParagraphStyle(name) {
572
+ const handle = native.mp_paragraph_style_create?.(name);
573
+ if (!handle || handle === 0) {
574
+ throw new Error('Failed to create paragraph style');
575
+ }
576
+ return { _handle: handle };
577
+ }
578
+ /**
579
+ * Free a paragraph style
580
+ */
581
+ export function freeParagraphStyle(style) {
582
+ native.mp_paragraph_style_free?.(style._handle);
583
+ }
584
+ /**
585
+ * Set paragraph style font size
586
+ */
587
+ export function setParagraphStyleFontSize(style, size) {
588
+ native.mp_paragraph_style_set_font_size?.(style._handle, size);
589
+ }
590
+ /**
591
+ * Set paragraph style leading
592
+ */
593
+ export function setParagraphStyleLeading(style, leading) {
594
+ native.mp_paragraph_style_set_leading?.(style._handle, leading);
595
+ }
596
+ /**
597
+ * Set paragraph style alignment
598
+ */
599
+ export function setParagraphStyleAlignment(style, align) {
600
+ native.mp_paragraph_style_set_alignment?.(style._handle, align);
601
+ }
602
+ /**
603
+ * Create a spacer
604
+ */
605
+ export function createSpacer(height) {
606
+ const handle = native.mp_spacer_create?.(height);
607
+ if (!handle || handle === 0) {
608
+ throw new Error('Failed to create spacer');
609
+ }
610
+ return { _handle: handle };
611
+ }
612
+ /**
613
+ * Free a spacer
614
+ */
615
+ export function freeSpacer(spacer) {
616
+ native.mp_spacer_free?.(spacer._handle);
617
+ }
618
+ /**
619
+ * Create a horizontal rule
620
+ */
621
+ export function createHorizontalRule() {
622
+ const handle = native.mp_hr_create?.();
623
+ if (!handle || handle === 0) {
624
+ throw new Error('Failed to create horizontal rule');
625
+ }
626
+ return { _handle: handle };
627
+ }
628
+ /**
629
+ * Free a horizontal rule
630
+ */
631
+ export function freeHorizontalRule(hr) {
632
+ native.mp_hr_free?.(hr._handle);
633
+ }
634
+ /**
635
+ * Set horizontal rule thickness
636
+ */
637
+ export function setHorizontalRuleThickness(hr, thickness) {
638
+ native.mp_hr_set_thickness?.(hr._handle, thickness);
639
+ }
640
+ /**
641
+ * Create an image flowable
642
+ */
643
+ export function createImage(path) {
644
+ const handle = native.mp_image_create?.(path);
645
+ if (!handle || handle === 0) {
646
+ throw new Error('Failed to create image');
647
+ }
648
+ return { _handle: handle };
649
+ }
650
+ /**
651
+ * Free an image
652
+ */
653
+ export function freeImage(image) {
654
+ native.mp_image_free?.(image._handle);
655
+ }
656
+ /**
657
+ * Set image width
658
+ */
659
+ export function setImageWidth(image, width) {
660
+ native.mp_image_set_width?.(image._handle, width);
661
+ }
662
+ /**
663
+ * Set image height
664
+ */
665
+ export function setImageHeight(image, height) {
666
+ native.mp_image_set_height?.(image._handle, height);
667
+ }
668
+ /**
669
+ * Create a bullet list item
670
+ */
671
+ export function createBulletListItem(text) {
672
+ const handle = native.mp_list_item_bullet?.(text);
673
+ if (!handle || handle === 0) {
674
+ throw new Error('Failed to create bullet list item');
675
+ }
676
+ return { _handle: handle };
677
+ }
678
+ /**
679
+ * Create a numbered list item
680
+ */
681
+ export function createNumberedListItem(number, text) {
682
+ const handle = native.mp_list_item_numbered?.(number, text);
683
+ if (!handle || handle === 0) {
684
+ throw new Error('Failed to create numbered list item');
685
+ }
686
+ return { _handle: handle };
687
+ }
688
+ /**
689
+ * Free a list item
690
+ */
691
+ export function freeListItem(item) {
692
+ native.mp_list_item_free?.(item._handle);
693
+ }
694
+ // ============================================================================
695
+ // Tables
696
+ // ============================================================================
697
+ /**
698
+ * Create a table
699
+ */
700
+ export function createTable(rows, cols) {
701
+ const handle = native.mp_table_create?.(rows, cols);
702
+ if (!handle || handle === 0) {
703
+ throw new Error('Failed to create table');
704
+ }
705
+ return { _handle: handle };
706
+ }
707
+ /**
708
+ * Free a table
709
+ */
710
+ export function freeTable(table) {
711
+ native.mp_table_free?.(table._handle);
712
+ }
713
+ /**
714
+ * Get table row count
715
+ */
716
+ export function getTableRowCount(table) {
717
+ return native.mp_table_num_rows?.(table._handle) ?? 0;
718
+ }
719
+ /**
720
+ * Get table column count
721
+ */
722
+ export function getTableColCount(table) {
723
+ return native.mp_table_num_cols?.(table._handle) ?? 0;
724
+ }
725
+ /**
726
+ * Create a table style
727
+ */
728
+ export function createTableStyle() {
729
+ const handle = native.mp_table_style_create?.();
730
+ if (!handle || handle === 0) {
731
+ throw new Error('Failed to create table style');
732
+ }
733
+ return { _handle: handle };
734
+ }
735
+ /**
736
+ * Free a table style
737
+ */
738
+ export function freeTableStyle(style) {
739
+ native.mp_table_style_free?.(style._handle);
740
+ }
741
+ /**
742
+ * Add grid to table style
743
+ */
744
+ export function addTableGrid(style, weight, r, g, b) {
745
+ native.mp_table_style_add_grid?.(style._handle, weight, r, g, b);
746
+ }
747
+ /**
748
+ * Add background to table style
749
+ */
750
+ export function addTableBackground(style, startCol, startRow, endCol, endRow, r, g, b) {
751
+ native.mp_table_style_add_background?.(style._handle, startCol, startRow, endCol, endRow, r, g, b);
752
+ }
753
+ // ============================================================================
754
+ // Table of Contents
755
+ // ============================================================================
756
+ /**
757
+ * Create a table of contents
758
+ */
759
+ export function createToc() {
760
+ const handle = native.mp_toc_create?.();
761
+ if (!handle || handle === 0) {
762
+ throw new Error('Failed to create table of contents');
763
+ }
764
+ return { _handle: handle };
765
+ }
766
+ /**
767
+ * Free a table of contents
768
+ */
769
+ export function freeToc(toc) {
770
+ native.mp_toc_free?.(toc._handle);
771
+ }
772
+ /**
773
+ * Set TOC title
774
+ */
775
+ export function setTocTitle(toc, title) {
776
+ native.mp_toc_set_title?.(toc._handle, title);
777
+ }
778
+ /**
779
+ * Add TOC entry
780
+ */
781
+ export function addTocEntry(toc, title, level, page) {
782
+ native.mp_toc_add_entry?.(toc._handle, title, level, page);
783
+ }
784
+ /**
785
+ * Create a TOC builder
786
+ */
787
+ export function createTocBuilder() {
788
+ const handle = native.mp_toc_builder_create?.();
789
+ if (!handle || handle === 0) {
790
+ throw new Error('Failed to create TOC builder');
791
+ }
792
+ return { _handle: handle };
793
+ }
794
+ /**
795
+ * Free a TOC builder
796
+ */
797
+ export function freeTocBuilder(builder) {
798
+ native.mp_toc_builder_free?.(builder._handle);
799
+ }
800
+ /**
801
+ * Add heading to TOC builder
802
+ */
803
+ export function addTocHeading(builder, title, level, page) {
804
+ native.mp_toc_builder_add_heading?.(builder._handle, title, level, page);
805
+ }
806
+ // ============================================================================
807
+ // Story (Document Flow)
808
+ // ============================================================================
809
+ /**
810
+ * Create a story
811
+ */
812
+ export function createStory() {
813
+ const handle = native.mp_story_create?.();
814
+ if (!handle || handle === 0) {
815
+ throw new Error('Failed to create story');
816
+ }
817
+ return { _handle: handle };
818
+ }
819
+ /**
820
+ * Free a story
821
+ */
822
+ export function freeStory(story) {
823
+ native.mp_story_free?.(story._handle);
824
+ }
825
+ /**
826
+ * Get story length (number of flowables)
827
+ */
828
+ export function getStoryLength(story) {
829
+ return native.mp_story_len?.(story._handle) ?? 0;
830
+ }
831
+ // ============================================================================
832
+ // Stylesheets
833
+ // ============================================================================
834
+ /**
835
+ * Create a stylesheet
836
+ */
837
+ export function createStyleSheet() {
838
+ const handle = native.mp_stylesheet_create?.();
839
+ if (!handle || handle === 0) {
840
+ throw new Error('Failed to create stylesheet');
841
+ }
842
+ return { _handle: handle };
843
+ }
844
+ /**
845
+ * Free a stylesheet
846
+ */
847
+ export function freeStyleSheet(sheet) {
848
+ native.mp_stylesheet_free?.(sheet._handle);
849
+ }
850
+ /**
851
+ * Add style to stylesheet
852
+ */
853
+ export function addStyleToSheet(sheet, style) {
854
+ native.mp_stylesheet_add_style?.(sheet._handle, style._handle);
855
+ }
856
+ // ============================================================================
857
+ // PDF Validation & Repair
858
+ // ============================================================================
859
+ /**
860
+ * Validate a PDF
861
+ */
862
+ export function validatePdf(pdfPath, mode = ValidationMode.Standard) {
863
+ const result = { valid: true, errors: [], warnings: [] };
864
+ const status = native.mp_validate_pdf?.(pdfPath, mode, result);
865
+ if (status !== 0) {
866
+ result.valid = false;
867
+ }
868
+ return result;
869
+ }
870
+ /**
871
+ * Quick validate a PDF (basic structure check)
872
+ */
873
+ export function quickValidatePdf(pdfPath) {
874
+ return native.mp_quick_validate?.(pdfPath) === 0;
875
+ }
876
+ /**
877
+ * Repair a PDF
878
+ */
879
+ export function repairPdf(inputPath, outputPath) {
880
+ const result = native.mp_repair_pdf?.(inputPath, outputPath);
881
+ if (result !== 0) {
882
+ throw new Error('Failed to repair PDF');
883
+ }
884
+ }
885
+ // ============================================================================
886
+ // PDF Operations
887
+ // ============================================================================
888
+ /**
889
+ * Merge multiple PDFs
890
+ */
891
+ export function mergePdfs(ctx, paths, outputPath) {
892
+ const result = native.npMergePDFs(ctx, paths, paths.length, outputPath);
893
+ if (result !== 0) {
894
+ throw new Error('Failed to merge PDFs');
895
+ }
896
+ }
897
+ /**
898
+ * Split a PDF into individual pages
899
+ */
900
+ export function splitPdf(ctx, inputPath, outputDir) {
901
+ return native.npSplitPDF(ctx, inputPath, outputDir);
902
+ }
903
+ /**
904
+ * Optimize a PDF (compress, remove unused objects)
905
+ */
906
+ export function optimizePdf(ctx, path) {
907
+ native.npOptimizePDF(ctx, path);
908
+ }
909
+ /**
910
+ * Linearize a PDF for fast web viewing
911
+ */
912
+ export function linearizePdf(ctx, inputPath, outputPath) {
913
+ native.npLinearizePDF(ctx, inputPath, outputPath);
914
+ }
915
+ /**
916
+ * Add a blank page to a document
917
+ */
918
+ export function addBlankPage(ctx, doc, width, height) {
919
+ return native.npAddBlankPage(ctx, doc, width, height);
920
+ }
921
+ /**
922
+ * Add a watermark to a document
923
+ */
924
+ export function addWatermark(ctx, doc, text, fontSize, opacity) {
925
+ native.npAddWatermark(ctx, doc, text, fontSize, opacity);
926
+ }
927
+ /**
928
+ * Draw a line on a page
929
+ */
930
+ export function drawLine(ctx, page, x0, y0, x1, y1, color, alpha, lineWidth) {
931
+ native.npDrawLine(ctx, page, x0, y0, x1, y1, color, alpha, lineWidth);
932
+ }
933
+ /**
934
+ * Draw a rectangle on a page
935
+ */
936
+ export function drawRectangle(ctx, page, x, y, width, height, color, alpha, fill) {
937
+ native.npDrawRectangle(ctx, page, x, y, width, height, color, alpha, fill);
938
+ }
939
+ /**
940
+ * Draw a circle on a page
941
+ */
942
+ export function drawCircle(ctx, page, x, y, radius, color, alpha, fill) {
943
+ native.npDrawCircle(ctx, page, x, y, radius, color, alpha, fill);
944
+ }
945
+ // ============================================================================
946
+ // Memory Management
947
+ // ============================================================================
948
+ /**
949
+ * Free a string allocated by the native library
950
+ */
951
+ export function freeString(s) {
952
+ native.mp_free_string?.(s);
367
953
  }
954
+ // ============================================================================
955
+ // Export all types and functions
956
+ // ============================================================================
957
+ export * from './native.js';
368
958
  //# sourceMappingURL=enhanced.js.map