@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/native/form.cc ADDED
@@ -0,0 +1,523 @@
1
+ /**
2
+ * MicroPDF Form Field Bindings
3
+ *
4
+ * N-API bindings for PDF interactive form (AcroForm) operations.
5
+ * Supports creating, reading, and modifying form fields.
6
+ */
7
+
8
+ #include <napi.h>
9
+ #include "include/mupdf_minimal.h"
10
+ #include <string>
11
+
12
+ /**
13
+ * Get first form field widget on page
14
+ *
15
+ * @param ctx - Context handle
16
+ * @param page - Page handle
17
+ * @returns Widget handle (or 0 if none)
18
+ */
19
+ Napi::BigInt GetPageWidget(const Napi::CallbackInfo& info) {
20
+ Napi::Env env = info.Env();
21
+
22
+ if (info.Length() < 2) {
23
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, page")
24
+ .ThrowAsJavaScriptException();
25
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
26
+ }
27
+
28
+ bool lossless;
29
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
30
+ uint64_t page_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
31
+
32
+ // Call Rust FFI
33
+ uint64_t widget_handle = pdf_first_widget(ctx_handle, page_handle);
34
+
35
+ return Napi::BigInt::New(env, widget_handle);
36
+ }
37
+
38
+ /**
39
+ * Get next widget in list
40
+ *
41
+ * @param ctx - Context handle
42
+ * @param widget - Current widget handle
43
+ * @returns Next widget handle (or 0 if none)
44
+ */
45
+ Napi::BigInt GetNextWidget(const Napi::CallbackInfo& info) {
46
+ Napi::Env env = info.Env();
47
+
48
+ if (info.Length() < 2) {
49
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
50
+ .ThrowAsJavaScriptException();
51
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
52
+ }
53
+
54
+ bool lossless;
55
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
56
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
57
+
58
+ uint64_t next_handle = pdf_next_widget(ctx_handle, widget_handle);
59
+
60
+ return Napi::BigInt::New(env, next_handle);
61
+ }
62
+
63
+ /**
64
+ * Drop widget handle
65
+ *
66
+ * @param ctx - Context handle
67
+ * @param widget - Widget handle
68
+ */
69
+ Napi::Value DropWidget(const Napi::CallbackInfo& info) {
70
+ Napi::Env env = info.Env();
71
+
72
+ if (info.Length() < 2) {
73
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
74
+ .ThrowAsJavaScriptException();
75
+ return env.Undefined();
76
+ }
77
+
78
+ bool lossless;
79
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
80
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
81
+
82
+ pdf_drop_widget(ctx_handle, widget_handle);
83
+
84
+ return env.Undefined();
85
+ }
86
+
87
+ /**
88
+ * Get widget field type
89
+ *
90
+ * @param ctx - Context handle
91
+ * @param widget - Widget handle
92
+ * @returns Field type number (0-6)
93
+ */
94
+ Napi::Number GetWidgetType(const Napi::CallbackInfo& info) {
95
+ Napi::Env env = info.Env();
96
+
97
+ if (info.Length() < 2) {
98
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
99
+ .ThrowAsJavaScriptException();
100
+ return Napi::Number::New(env, -1);
101
+ }
102
+
103
+ bool lossless;
104
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
105
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
106
+
107
+ int32_t field_type = pdf_widget_type(ctx_handle, widget_handle);
108
+
109
+ return Napi::Number::New(env, field_type);
110
+ }
111
+
112
+ /**
113
+ * Get widget field name
114
+ *
115
+ * @param ctx - Context handle
116
+ * @param widget - Widget handle
117
+ * @returns Field name string
118
+ */
119
+ Napi::String GetWidgetName(const Napi::CallbackInfo& info) {
120
+ Napi::Env env = info.Env();
121
+
122
+ if (info.Length() < 2) {
123
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
124
+ .ThrowAsJavaScriptException();
125
+ return Napi::String::New(env, "");
126
+ }
127
+
128
+ bool lossless;
129
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
130
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
131
+
132
+ // Allocate buffer for name
133
+ char buffer[256];
134
+ pdf_widget_name(ctx_handle, widget_handle, buffer, sizeof(buffer));
135
+
136
+ return Napi::String::New(env, buffer);
137
+ }
138
+
139
+ /**
140
+ * Get widget field value
141
+ *
142
+ * @param ctx - Context handle
143
+ * @param widget - Widget handle
144
+ * @returns Field value string
145
+ */
146
+ Napi::String GetWidgetValue(const Napi::CallbackInfo& info) {
147
+ Napi::Env env = info.Env();
148
+
149
+ if (info.Length() < 2) {
150
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
151
+ .ThrowAsJavaScriptException();
152
+ return Napi::String::New(env, "");
153
+ }
154
+
155
+ bool lossless;
156
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
157
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
158
+
159
+ char buffer[4096];
160
+ pdf_widget_value(ctx_handle, widget_handle, buffer, sizeof(buffer));
161
+
162
+ return Napi::String::New(env, buffer);
163
+ }
164
+
165
+ /**
166
+ * Set widget field value
167
+ *
168
+ * @param ctx - Context handle
169
+ * @param widget - Widget handle
170
+ * @param value - Value string
171
+ * @returns Success boolean
172
+ */
173
+ Napi::Boolean SetWidgetValue(const Napi::CallbackInfo& info) {
174
+ Napi::Env env = info.Env();
175
+
176
+ if (info.Length() < 3) {
177
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, widget, value")
178
+ .ThrowAsJavaScriptException();
179
+ return Napi::Boolean::New(env, false);
180
+ }
181
+
182
+ bool lossless;
183
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
184
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
185
+ std::string value = info[2].As<Napi::String>().Utf8Value();
186
+
187
+ int32_t result = pdf_set_widget_value(ctx_handle, widget_handle, value.c_str());
188
+
189
+ return Napi::Boolean::New(env, result != 0);
190
+ }
191
+
192
+ /**
193
+ * Get widget rectangle
194
+ *
195
+ * @param ctx - Context handle
196
+ * @param widget - Widget handle
197
+ * @returns Rectangle {x0, y0, x1, y1}
198
+ */
199
+ Napi::Object GetWidgetRect(const Napi::CallbackInfo& info) {
200
+ Napi::Env env = info.Env();
201
+ Napi::Object rect = Napi::Object::New(env);
202
+
203
+ if (info.Length() < 2) {
204
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
205
+ .ThrowAsJavaScriptException();
206
+ return rect;
207
+ }
208
+
209
+ bool lossless;
210
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
211
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
212
+
213
+ fz_rect widget_rect = pdf_widget_rect(ctx_handle, widget_handle);
214
+
215
+ rect.Set("x0", Napi::Number::New(env, widget_rect.x0));
216
+ rect.Set("y0", Napi::Number::New(env, widget_rect.y0));
217
+ rect.Set("x1", Napi::Number::New(env, widget_rect.x1));
218
+ rect.Set("y1", Napi::Number::New(env, widget_rect.y1));
219
+
220
+ return rect;
221
+ }
222
+
223
+ /**
224
+ * Check if widget is read-only
225
+ *
226
+ * @param ctx - Context handle
227
+ * @param widget - Widget handle
228
+ * @returns Boolean
229
+ */
230
+ Napi::Boolean IsWidgetReadOnly(const Napi::CallbackInfo& info) {
231
+ Napi::Env env = info.Env();
232
+
233
+ if (info.Length() < 2) {
234
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
235
+ .ThrowAsJavaScriptException();
236
+ return Napi::Boolean::New(env, false);
237
+ }
238
+
239
+ bool lossless;
240
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
241
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
242
+
243
+ int32_t is_readonly = pdf_widget_is_readonly(ctx_handle, widget_handle);
244
+
245
+ return Napi::Boolean::New(env, is_readonly != 0);
246
+ }
247
+
248
+ /**
249
+ * Check if widget is required
250
+ *
251
+ * @param ctx - Context handle
252
+ * @param widget - Widget handle
253
+ * @returns Boolean
254
+ */
255
+ Napi::Boolean IsWidgetRequired(const Napi::CallbackInfo& info) {
256
+ Napi::Env env = info.Env();
257
+
258
+ if (info.Length() < 2) {
259
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
260
+ .ThrowAsJavaScriptException();
261
+ return Napi::Boolean::New(env, false);
262
+ }
263
+
264
+ bool lossless;
265
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
266
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
267
+
268
+ int32_t is_required = pdf_widget_is_required(ctx_handle, widget_handle);
269
+
270
+ return Napi::Boolean::New(env, is_required != 0);
271
+ }
272
+
273
+ /**
274
+ * Get widget max length (for text fields)
275
+ *
276
+ * @param ctx - Context handle
277
+ * @param widget - Widget handle
278
+ * @returns Max length (-1 if unlimited)
279
+ */
280
+ Napi::Number GetWidgetMaxLen(const Napi::CallbackInfo& info) {
281
+ Napi::Env env = info.Env();
282
+
283
+ if (info.Length() < 2) {
284
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
285
+ .ThrowAsJavaScriptException();
286
+ return Napi::Number::New(env, -1);
287
+ }
288
+
289
+ bool lossless;
290
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
291
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
292
+
293
+ int32_t max_len = pdf_widget_max_len(ctx_handle, widget_handle);
294
+
295
+ return Napi::Number::New(env, max_len);
296
+ }
297
+
298
+ /**
299
+ * Get widget choice options (for combo/list boxes)
300
+ *
301
+ * @param ctx - Context handle
302
+ * @param widget - Widget handle
303
+ * @returns Array of option strings
304
+ */
305
+ Napi::Array GetWidgetOptions(const Napi::CallbackInfo& info) {
306
+ Napi::Env env = info.Env();
307
+ Napi::Array options = Napi::Array::New(env);
308
+
309
+ if (info.Length() < 2) {
310
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
311
+ .ThrowAsJavaScriptException();
312
+ return options;
313
+ }
314
+
315
+ bool lossless;
316
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
317
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
318
+
319
+ // Get option count
320
+ int32_t count = pdf_widget_option_count(ctx_handle, widget_handle);
321
+
322
+ // Get each option
323
+ for (int32_t i = 0; i < count; i++) {
324
+ char buffer[256];
325
+ pdf_widget_option(ctx_handle, widget_handle, i, buffer, sizeof(buffer));
326
+ options.Set(static_cast<uint32_t>(i), Napi::String::New(env, buffer));
327
+ }
328
+
329
+ return options;
330
+ }
331
+
332
+ /**
333
+ * Update widget appearance
334
+ *
335
+ * @param ctx - Context handle
336
+ * @param widget - Widget handle
337
+ * @returns Success boolean
338
+ */
339
+ Napi::Boolean UpdateWidget(const Napi::CallbackInfo& info) {
340
+ Napi::Env env = info.Env();
341
+
342
+ if (info.Length() < 2) {
343
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
344
+ .ThrowAsJavaScriptException();
345
+ return Napi::Boolean::New(env, false);
346
+ }
347
+
348
+ bool lossless;
349
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
350
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
351
+
352
+ int32_t result = pdf_update_widget(ctx_handle, widget_handle);
353
+
354
+ return Napi::Boolean::New(env, result != 0);
355
+ }
356
+
357
+ /**
358
+ * Check if widget is valid
359
+ *
360
+ * @param ctx - Context handle
361
+ * @param widget - Widget handle
362
+ * @returns Boolean
363
+ */
364
+ Napi::Boolean IsWidgetValid(const Napi::CallbackInfo& info) {
365
+ Napi::Env env = info.Env();
366
+
367
+ if (info.Length() < 2) {
368
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
369
+ .ThrowAsJavaScriptException();
370
+ return Napi::Boolean::New(env, false);
371
+ }
372
+
373
+ bool lossless;
374
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
375
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
376
+
377
+ int32_t is_valid = pdf_widget_is_valid(ctx_handle, widget_handle);
378
+
379
+ return Napi::Boolean::New(env, is_valid != 0);
380
+ }
381
+
382
+ /**
383
+ * Get widget text format (for text fields)
384
+ *
385
+ * @param ctx - Context handle
386
+ * @param widget - Widget handle
387
+ * @returns Format number (0=None, 1=Number, 2=Special, 3=Date, 4=Time)
388
+ */
389
+ Napi::Number GetWidgetTextFormat(const Napi::CallbackInfo& info) {
390
+ Napi::Env env = info.Env();
391
+
392
+ if (info.Length() < 2) {
393
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
394
+ .ThrowAsJavaScriptException();
395
+ return Napi::Number::New(env, 0);
396
+ }
397
+
398
+ bool lossless;
399
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
400
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
401
+
402
+ int32_t format = pdf_widget_text_format(ctx_handle, widget_handle);
403
+
404
+ return Napi::Number::New(env, format);
405
+ }
406
+
407
+ /**
408
+ * Check if text field is multiline
409
+ *
410
+ * @param ctx - Context handle
411
+ * @param widget - Widget handle
412
+ * @returns Boolean
413
+ */
414
+ Napi::Boolean IsWidgetMultiline(const Napi::CallbackInfo& info) {
415
+ Napi::Env env = info.Env();
416
+
417
+ if (info.Length() < 2) {
418
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
419
+ .ThrowAsJavaScriptException();
420
+ return Napi::Boolean::New(env, false);
421
+ }
422
+
423
+ bool lossless;
424
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
425
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
426
+
427
+ int32_t is_multiline = pdf_widget_is_multiline(ctx_handle, widget_handle);
428
+
429
+ return Napi::Boolean::New(env, is_multiline != 0);
430
+ }
431
+
432
+ /**
433
+ * Check if checkbox/radio is checked
434
+ *
435
+ * @param ctx - Context handle
436
+ * @param widget - Widget handle
437
+ * @returns Boolean
438
+ */
439
+ Napi::Boolean IsWidgetChecked(const Napi::CallbackInfo& info) {
440
+ Napi::Env env = info.Env();
441
+
442
+ if (info.Length() < 2) {
443
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, widget")
444
+ .ThrowAsJavaScriptException();
445
+ return Napi::Boolean::New(env, false);
446
+ }
447
+
448
+ bool lossless;
449
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
450
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
451
+
452
+ int32_t is_checked = pdf_widget_is_checked(ctx_handle, widget_handle);
453
+
454
+ return Napi::Boolean::New(env, is_checked != 0);
455
+ }
456
+
457
+ /**
458
+ * Set checkbox/radio checked state
459
+ *
460
+ * @param ctx - Context handle
461
+ * @param widget - Widget handle
462
+ * @param checked - Boolean state
463
+ */
464
+ Napi::Value SetWidgetChecked(const Napi::CallbackInfo& info) {
465
+ Napi::Env env = info.Env();
466
+
467
+ if (info.Length() < 3) {
468
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, widget, checked")
469
+ .ThrowAsJavaScriptException();
470
+ return env.Undefined();
471
+ }
472
+
473
+ bool lossless;
474
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
475
+ uint64_t widget_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
476
+ bool checked = info[2].As<Napi::Boolean>().Value();
477
+
478
+ pdf_set_widget_checked(ctx_handle, widget_handle, checked ? 1 : 0);
479
+
480
+ return env.Undefined();
481
+ }
482
+
483
+ /**
484
+ * Initialize Form module exports
485
+ */
486
+ Napi::Object InitForm(Napi::Env env, Napi::Object exports) {
487
+ // Widget navigation
488
+ exports.Set("getPageWidget", Napi::Function::New(env, GetPageWidget));
489
+ exports.Set("getNextWidget", Napi::Function::New(env, GetNextWidget));
490
+ exports.Set("dropWidget", Napi::Function::New(env, DropWidget));
491
+
492
+ // Widget properties
493
+ exports.Set("getWidgetType", Napi::Function::New(env, GetWidgetType));
494
+ exports.Set("getWidgetName", Napi::Function::New(env, GetWidgetName));
495
+ exports.Set("getWidgetRect", Napi::Function::New(env, GetWidgetRect));
496
+
497
+ // Widget values
498
+ exports.Set("getWidgetValue", Napi::Function::New(env, GetWidgetValue));
499
+ exports.Set("setWidgetValue", Napi::Function::New(env, SetWidgetValue));
500
+
501
+ // Widget state
502
+ exports.Set("isWidgetReadOnly", Napi::Function::New(env, IsWidgetReadOnly));
503
+ exports.Set("isWidgetRequired", Napi::Function::New(env, IsWidgetRequired));
504
+ exports.Set("isWidgetValid", Napi::Function::New(env, IsWidgetValid));
505
+
506
+ // Text field specific
507
+ exports.Set("getWidgetTextFormat", Napi::Function::New(env, GetWidgetTextFormat));
508
+ exports.Set("getWidgetMaxLen", Napi::Function::New(env, GetWidgetMaxLen));
509
+ exports.Set("isWidgetMultiline", Napi::Function::New(env, IsWidgetMultiline));
510
+
511
+ // Checkbox/radio specific
512
+ exports.Set("isWidgetChecked", Napi::Function::New(env, IsWidgetChecked));
513
+ exports.Set("setWidgetChecked", Napi::Function::New(env, SetWidgetChecked));
514
+
515
+ // Choice field specific
516
+ exports.Set("getWidgetOptions", Napi::Function::New(env, GetWidgetOptions));
517
+
518
+ // Widget updates
519
+ exports.Set("updateWidget", Napi::Function::New(env, UpdateWidget));
520
+
521
+ return exports;
522
+ }
523
+