@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
@@ -0,0 +1,557 @@
1
+ /**
2
+ * MicroPDF Annotation Bindings
3
+ *
4
+ * N-API bindings for PDF annotation operations.
5
+ * Supports creating, modifying, and managing annotations.
6
+ */
7
+
8
+ #include <napi.h>
9
+ #include "include/mupdf_minimal.h"
10
+ #include <string>
11
+
12
+ /**
13
+ * Create a new annotation on a page
14
+ *
15
+ * @param ctx - Context handle
16
+ * @param page - Page handle
17
+ * @param type - Annotation type (0-27)
18
+ * @returns Annotation handle
19
+ */
20
+ Napi::BigInt CreateAnnotation(const Napi::CallbackInfo& info) {
21
+ Napi::Env env = info.Env();
22
+
23
+ if (info.Length() < 3) {
24
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, page, type")
25
+ .ThrowAsJavaScriptException();
26
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
27
+ }
28
+
29
+ bool lossless;
30
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
31
+ uint64_t page_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
32
+ int32_t annot_type = info[2].As<Napi::Number>().Int32Value();
33
+
34
+ // Validate annotation type (0-27)
35
+ if (annot_type < 0 || annot_type > 27) {
36
+ Napi::TypeError::New(env, "Invalid annotation type (must be 0-27)")
37
+ .ThrowAsJavaScriptException();
38
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
39
+ }
40
+
41
+ // Call Rust FFI
42
+ uint64_t annot_handle = pdf_create_annot(ctx_handle, page_handle, annot_type);
43
+
44
+ return Napi::BigInt::New(env, annot_handle);
45
+ }
46
+
47
+ /**
48
+ * Delete an annotation
49
+ *
50
+ * @param ctx - Context handle
51
+ * @param page - Page handle
52
+ * @param annot - Annotation handle
53
+ */
54
+ Napi::Value DeleteAnnotation(const Napi::CallbackInfo& info) {
55
+ Napi::Env env = info.Env();
56
+
57
+ if (info.Length() < 3) {
58
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, page, annot")
59
+ .ThrowAsJavaScriptException();
60
+ return env.Undefined();
61
+ }
62
+
63
+ bool lossless;
64
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
65
+ uint64_t page_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
66
+ uint64_t annot_handle = info[2].As<Napi::BigInt>().Uint64Value(&lossless);
67
+
68
+ pdf_delete_annot(ctx_handle, page_handle, annot_handle);
69
+
70
+ return env.Undefined();
71
+ }
72
+
73
+ /**
74
+ * Drop annotation handle
75
+ *
76
+ * @param ctx - Context handle
77
+ * @param annot - Annotation handle
78
+ */
79
+ Napi::Value DropAnnotation(const Napi::CallbackInfo& info) {
80
+ Napi::Env env = info.Env();
81
+
82
+ if (info.Length() < 2) {
83
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
84
+ .ThrowAsJavaScriptException();
85
+ return env.Undefined();
86
+ }
87
+
88
+ bool lossless;
89
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
90
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
91
+
92
+ pdf_drop_annot(ctx_handle, annot_handle);
93
+
94
+ return env.Undefined();
95
+ }
96
+
97
+ /**
98
+ * Get annotation type
99
+ *
100
+ * @param ctx - Context handle
101
+ * @param annot - Annotation handle
102
+ * @returns Annotation type number
103
+ */
104
+ Napi::Number GetAnnotationType(const Napi::CallbackInfo& info) {
105
+ Napi::Env env = info.Env();
106
+
107
+ if (info.Length() < 2) {
108
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
109
+ .ThrowAsJavaScriptException();
110
+ return Napi::Number::New(env, -1);
111
+ }
112
+
113
+ bool lossless;
114
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
115
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
116
+
117
+ int32_t type = pdf_annot_type(ctx_handle, annot_handle);
118
+
119
+ return Napi::Number::New(env, type);
120
+ }
121
+
122
+ /**
123
+ * Get annotation rectangle
124
+ *
125
+ * @param ctx - Context handle
126
+ * @param annot - Annotation handle
127
+ * @returns Rectangle {x0, y0, x1, y1}
128
+ */
129
+ Napi::Object GetAnnotationRect(const Napi::CallbackInfo& info) {
130
+ Napi::Env env = info.Env();
131
+ Napi::Object rect = Napi::Object::New(env);
132
+
133
+ if (info.Length() < 2) {
134
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
135
+ .ThrowAsJavaScriptException();
136
+ return rect;
137
+ }
138
+
139
+ bool lossless;
140
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
141
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
142
+
143
+ fz_rect annot_rect = pdf_annot_rect(ctx_handle, annot_handle);
144
+
145
+ rect.Set("x0", Napi::Number::New(env, annot_rect.x0));
146
+ rect.Set("y0", Napi::Number::New(env, annot_rect.y0));
147
+ rect.Set("x1", Napi::Number::New(env, annot_rect.x1));
148
+ rect.Set("y1", Napi::Number::New(env, annot_rect.y1));
149
+
150
+ return rect;
151
+ }
152
+
153
+ /**
154
+ * Set annotation rectangle
155
+ *
156
+ * @param ctx - Context handle
157
+ * @param annot - Annotation handle
158
+ * @param rect - Rectangle {x0, y0, x1, y1}
159
+ */
160
+ Napi::Value SetAnnotationRect(const Napi::CallbackInfo& info) {
161
+ Napi::Env env = info.Env();
162
+
163
+ if (info.Length() < 3) {
164
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, annot, rect")
165
+ .ThrowAsJavaScriptException();
166
+ return env.Undefined();
167
+ }
168
+
169
+ bool lossless;
170
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
171
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
172
+
173
+ Napi::Object rect_obj = info[2].As<Napi::Object>();
174
+ fz_rect rect;
175
+ rect.x0 = rect_obj.Get("x0").As<Napi::Number>().FloatValue();
176
+ rect.y0 = rect_obj.Get("y0").As<Napi::Number>().FloatValue();
177
+ rect.x1 = rect_obj.Get("x1").As<Napi::Number>().FloatValue();
178
+ rect.y1 = rect_obj.Get("y1").As<Napi::Number>().FloatValue();
179
+
180
+ pdf_set_annot_rect(ctx_handle, annot_handle, rect);
181
+
182
+ return env.Undefined();
183
+ }
184
+
185
+ /**
186
+ * Get annotation flags
187
+ *
188
+ * @param ctx - Context handle
189
+ * @param annot - Annotation handle
190
+ * @returns Flags as number
191
+ */
192
+ Napi::Number GetAnnotationFlags(const Napi::CallbackInfo& info) {
193
+ Napi::Env env = info.Env();
194
+
195
+ if (info.Length() < 2) {
196
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
197
+ .ThrowAsJavaScriptException();
198
+ return Napi::Number::New(env, 0);
199
+ }
200
+
201
+ bool lossless;
202
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
203
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
204
+
205
+ uint32_t flags = pdf_annot_flags(ctx_handle, annot_handle);
206
+
207
+ return Napi::Number::New(env, flags);
208
+ }
209
+
210
+ /**
211
+ * Set annotation flags
212
+ *
213
+ * @param ctx - Context handle
214
+ * @param annot - Annotation handle
215
+ * @param flags - Flags as number
216
+ */
217
+ Napi::Value SetAnnotationFlags(const Napi::CallbackInfo& info) {
218
+ Napi::Env env = info.Env();
219
+
220
+ if (info.Length() < 3) {
221
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, annot, flags")
222
+ .ThrowAsJavaScriptException();
223
+ return env.Undefined();
224
+ }
225
+
226
+ bool lossless;
227
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
228
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
229
+ uint32_t flags = info[2].As<Napi::Number>().Uint32Value();
230
+
231
+ pdf_set_annot_flags(ctx_handle, annot_handle, flags);
232
+
233
+ return env.Undefined();
234
+ }
235
+
236
+ /**
237
+ * Get annotation contents
238
+ *
239
+ * @param ctx - Context handle
240
+ * @param annot - Annotation handle
241
+ * @returns Contents string
242
+ */
243
+ Napi::String GetAnnotationContents(const Napi::CallbackInfo& info) {
244
+ Napi::Env env = info.Env();
245
+
246
+ if (info.Length() < 2) {
247
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
248
+ .ThrowAsJavaScriptException();
249
+ return Napi::String::New(env, "");
250
+ }
251
+
252
+ bool lossless;
253
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
254
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
255
+
256
+ // Allocate buffer for contents
257
+ char buffer[4096];
258
+ pdf_annot_contents(ctx_handle, annot_handle, buffer, sizeof(buffer));
259
+
260
+ return Napi::String::New(env, buffer);
261
+ }
262
+
263
+ /**
264
+ * Set annotation contents
265
+ *
266
+ * @param ctx - Context handle
267
+ * @param annot - Annotation handle
268
+ * @param contents - Contents string
269
+ */
270
+ Napi::Value SetAnnotationContents(const Napi::CallbackInfo& info) {
271
+ Napi::Env env = info.Env();
272
+
273
+ if (info.Length() < 3) {
274
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, annot, contents")
275
+ .ThrowAsJavaScriptException();
276
+ return env.Undefined();
277
+ }
278
+
279
+ bool lossless;
280
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
281
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
282
+ std::string contents = info[2].As<Napi::String>().Utf8Value();
283
+
284
+ pdf_set_annot_contents(ctx_handle, annot_handle, contents.c_str());
285
+
286
+ return env.Undefined();
287
+ }
288
+
289
+ /**
290
+ * Get annotation author
291
+ *
292
+ * @param ctx - Context handle
293
+ * @param annot - Annotation handle
294
+ * @returns Author string
295
+ */
296
+ Napi::String GetAnnotationAuthor(const Napi::CallbackInfo& info) {
297
+ Napi::Env env = info.Env();
298
+
299
+ if (info.Length() < 2) {
300
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
301
+ .ThrowAsJavaScriptException();
302
+ return Napi::String::New(env, "");
303
+ }
304
+
305
+ bool lossless;
306
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
307
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
308
+
309
+ char buffer[256];
310
+ pdf_annot_author(ctx_handle, annot_handle, buffer, sizeof(buffer));
311
+
312
+ return Napi::String::New(env, buffer);
313
+ }
314
+
315
+ /**
316
+ * Set annotation author
317
+ *
318
+ * @param ctx - Context handle
319
+ * @param annot - Annotation handle
320
+ * @param author - Author string
321
+ */
322
+ Napi::Value SetAnnotationAuthor(const Napi::CallbackInfo& info) {
323
+ Napi::Env env = info.Env();
324
+
325
+ if (info.Length() < 3) {
326
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, annot, author")
327
+ .ThrowAsJavaScriptException();
328
+ return env.Undefined();
329
+ }
330
+
331
+ bool lossless;
332
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
333
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
334
+ std::string author = info[2].As<Napi::String>().Utf8Value();
335
+
336
+ pdf_set_annot_author(ctx_handle, annot_handle, author.c_str());
337
+
338
+ return env.Undefined();
339
+ }
340
+
341
+ /**
342
+ * Get annotation opacity
343
+ *
344
+ * @param ctx - Context handle
345
+ * @param annot - Annotation handle
346
+ * @returns Opacity (0.0-1.0)
347
+ */
348
+ Napi::Number GetAnnotationOpacity(const Napi::CallbackInfo& info) {
349
+ Napi::Env env = info.Env();
350
+
351
+ if (info.Length() < 2) {
352
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
353
+ .ThrowAsJavaScriptException();
354
+ return Napi::Number::New(env, 1.0);
355
+ }
356
+
357
+ bool lossless;
358
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
359
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
360
+
361
+ float opacity = pdf_annot_opacity(ctx_handle, annot_handle);
362
+
363
+ return Napi::Number::New(env, opacity);
364
+ }
365
+
366
+ /**
367
+ * Set annotation opacity
368
+ *
369
+ * @param ctx - Context handle
370
+ * @param annot - Annotation handle
371
+ * @param opacity - Opacity (0.0-1.0)
372
+ */
373
+ Napi::Value SetAnnotationOpacity(const Napi::CallbackInfo& info) {
374
+ Napi::Env env = info.Env();
375
+
376
+ if (info.Length() < 3) {
377
+ Napi::TypeError::New(env, "Expected 3 arguments: ctx, annot, opacity")
378
+ .ThrowAsJavaScriptException();
379
+ return env.Undefined();
380
+ }
381
+
382
+ bool lossless;
383
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
384
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
385
+ float opacity = info[2].As<Napi::Number>().FloatValue();
386
+
387
+ // Clamp opacity to valid range
388
+ if (opacity < 0.0f) opacity = 0.0f;
389
+ if (opacity > 1.0f) opacity = 1.0f;
390
+
391
+ pdf_set_annot_opacity(ctx_handle, annot_handle, opacity);
392
+
393
+ return env.Undefined();
394
+ }
395
+
396
+ /**
397
+ * Check if annotation is dirty (modified)
398
+ *
399
+ * @param ctx - Context handle
400
+ * @param annot - Annotation handle
401
+ * @returns Boolean
402
+ */
403
+ Napi::Boolean IsAnnotationDirty(const Napi::CallbackInfo& info) {
404
+ Napi::Env env = info.Env();
405
+
406
+ if (info.Length() < 2) {
407
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
408
+ .ThrowAsJavaScriptException();
409
+ return Napi::Boolean::New(env, false);
410
+ }
411
+
412
+ bool lossless;
413
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
414
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
415
+
416
+ int32_t is_dirty = pdf_annot_has_dirty(ctx_handle, annot_handle);
417
+
418
+ return Napi::Boolean::New(env, is_dirty != 0);
419
+ }
420
+
421
+ /**
422
+ * Clear annotation dirty flag
423
+ *
424
+ * @param ctx - Context handle
425
+ * @param annot - Annotation handle
426
+ */
427
+ Napi::Value ClearAnnotationDirty(const Napi::CallbackInfo& info) {
428
+ Napi::Env env = info.Env();
429
+
430
+ if (info.Length() < 2) {
431
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
432
+ .ThrowAsJavaScriptException();
433
+ return env.Undefined();
434
+ }
435
+
436
+ bool lossless;
437
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
438
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
439
+
440
+ pdf_annot_clear_dirty(ctx_handle, annot_handle);
441
+
442
+ return env.Undefined();
443
+ }
444
+
445
+ /**
446
+ * Update annotation appearance
447
+ *
448
+ * @param ctx - Context handle
449
+ * @param annot - Annotation handle
450
+ * @returns Success boolean
451
+ */
452
+ Napi::Boolean UpdateAnnotation(const Napi::CallbackInfo& info) {
453
+ Napi::Env env = info.Env();
454
+
455
+ if (info.Length() < 2) {
456
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
457
+ .ThrowAsJavaScriptException();
458
+ return Napi::Boolean::New(env, false);
459
+ }
460
+
461
+ bool lossless;
462
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
463
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
464
+
465
+ int32_t result = pdf_update_annot(ctx_handle, annot_handle);
466
+
467
+ return Napi::Boolean::New(env, result != 0);
468
+ }
469
+
470
+ /**
471
+ * Clone an annotation
472
+ *
473
+ * @param ctx - Context handle
474
+ * @param annot - Annotation handle
475
+ * @returns New annotation handle
476
+ */
477
+ Napi::BigInt CloneAnnotation(const Napi::CallbackInfo& info) {
478
+ Napi::Env env = info.Env();
479
+
480
+ if (info.Length() < 2) {
481
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
482
+ .ThrowAsJavaScriptException();
483
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
484
+ }
485
+
486
+ bool lossless;
487
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
488
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
489
+
490
+ uint64_t new_annot = pdf_clone_annot(ctx_handle, annot_handle);
491
+
492
+ return Napi::BigInt::New(env, new_annot);
493
+ }
494
+
495
+ /**
496
+ * Check if annotation is valid
497
+ *
498
+ * @param ctx - Context handle
499
+ * @param annot - Annotation handle
500
+ * @returns Boolean
501
+ */
502
+ Napi::Boolean IsAnnotationValid(const Napi::CallbackInfo& info) {
503
+ Napi::Env env = info.Env();
504
+
505
+ if (info.Length() < 2) {
506
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, annot")
507
+ .ThrowAsJavaScriptException();
508
+ return Napi::Boolean::New(env, false);
509
+ }
510
+
511
+ bool lossless;
512
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
513
+ uint64_t annot_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
514
+
515
+ int32_t is_valid = pdf_annot_is_valid(ctx_handle, annot_handle);
516
+
517
+ return Napi::Boolean::New(env, is_valid != 0);
518
+ }
519
+
520
+ /**
521
+ * Initialize Annotation module exports
522
+ */
523
+ Napi::Object InitAnnotation(Napi::Env env, Napi::Object exports) {
524
+ // Annotation lifecycle
525
+ exports.Set("createAnnotation", Napi::Function::New(env, CreateAnnotation));
526
+ exports.Set("deleteAnnotation", Napi::Function::New(env, DeleteAnnotation));
527
+ exports.Set("dropAnnotation", Napi::Function::New(env, DropAnnotation));
528
+
529
+ // Annotation properties
530
+ exports.Set("getAnnotationType", Napi::Function::New(env, GetAnnotationType));
531
+ exports.Set("getAnnotationRect", Napi::Function::New(env, GetAnnotationRect));
532
+ exports.Set("setAnnotationRect", Napi::Function::New(env, SetAnnotationRect));
533
+ exports.Set("getAnnotationFlags", Napi::Function::New(env, GetAnnotationFlags));
534
+ exports.Set("setAnnotationFlags", Napi::Function::New(env, SetAnnotationFlags));
535
+
536
+ // Annotation content
537
+ exports.Set("getAnnotationContents", Napi::Function::New(env, GetAnnotationContents));
538
+ exports.Set("setAnnotationContents", Napi::Function::New(env, SetAnnotationContents));
539
+ exports.Set("getAnnotationAuthor", Napi::Function::New(env, GetAnnotationAuthor));
540
+ exports.Set("setAnnotationAuthor", Napi::Function::New(env, SetAnnotationAuthor));
541
+
542
+ // Annotation appearance
543
+ exports.Set("getAnnotationOpacity", Napi::Function::New(env, GetAnnotationOpacity));
544
+ exports.Set("setAnnotationOpacity", Napi::Function::New(env, SetAnnotationOpacity));
545
+
546
+ // Annotation state
547
+ exports.Set("isAnnotationDirty", Napi::Function::New(env, IsAnnotationDirty));
548
+ exports.Set("clearAnnotationDirty", Napi::Function::New(env, ClearAnnotationDirty));
549
+ exports.Set("updateAnnotation", Napi::Function::New(env, UpdateAnnotation));
550
+
551
+ // Annotation utilities
552
+ exports.Set("cloneAnnotation", Napi::Function::New(env, CloneAnnotation));
553
+ exports.Set("isAnnotationValid", Napi::Function::New(env, IsAnnotationValid));
554
+
555
+ return exports;
556
+ }
557
+