@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.
- package/LICENSE +191 -0
- package/README.md +985 -0
- package/binding.gyp +73 -0
- package/dist/annot.d.ts +458 -0
- package/dist/annot.d.ts.map +1 -0
- package/dist/annot.js +697 -0
- package/dist/annot.js.map +1 -0
- package/dist/archive.d.ts +128 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +268 -0
- package/dist/archive.js.map +1 -0
- package/dist/buffer.d.ts +572 -0
- package/dist/buffer.d.ts.map +1 -0
- package/dist/buffer.js +971 -0
- package/dist/buffer.js.map +1 -0
- package/dist/colorspace.d.ts +287 -0
- package/dist/colorspace.d.ts.map +1 -0
- package/dist/colorspace.js +542 -0
- package/dist/colorspace.js.map +1 -0
- package/dist/context.d.ts +184 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +320 -0
- package/dist/context.js.map +1 -0
- package/dist/cookie.d.ts +164 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +306 -0
- package/dist/cookie.js.map +1 -0
- package/dist/device.d.ts +169 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +350 -0
- package/dist/device.js.map +1 -0
- package/dist/display-list.d.ts +202 -0
- package/dist/display-list.d.ts.map +1 -0
- package/dist/display-list.js +410 -0
- package/dist/display-list.js.map +1 -0
- package/dist/document.d.ts +637 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +902 -0
- package/dist/document.js.map +1 -0
- package/dist/easy.d.ts +423 -0
- package/dist/easy.d.ts.map +1 -0
- package/dist/easy.js +644 -0
- package/dist/easy.js.map +1 -0
- package/dist/enhanced.d.ts +226 -0
- package/dist/enhanced.d.ts.map +1 -0
- package/dist/enhanced.js +368 -0
- package/dist/enhanced.js.map +1 -0
- package/dist/filter.d.ts +51 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +381 -0
- package/dist/filter.js.map +1 -0
- package/dist/font.d.ts +222 -0
- package/dist/font.d.ts.map +1 -0
- package/dist/font.js +381 -0
- package/dist/font.js.map +1 -0
- package/dist/form.d.ts +214 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +497 -0
- package/dist/form.js.map +1 -0
- package/dist/geometry.d.ts +469 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +780 -0
- package/dist/geometry.js.map +1 -0
- package/dist/image.d.ts +172 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +348 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +339 -0
- package/dist/index.js.map +1 -0
- package/dist/link.d.ts +168 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +343 -0
- package/dist/link.js.map +1 -0
- package/dist/micropdf.d.ts +40 -0
- package/dist/micropdf.d.ts.map +1 -0
- package/dist/micropdf.js +45 -0
- package/dist/micropdf.js.map +1 -0
- package/dist/nanopdf.d.ts +40 -0
- package/dist/nanopdf.d.ts.map +1 -0
- package/dist/nanopdf.js +45 -0
- package/dist/nanopdf.js.map +1 -0
- package/dist/native.d.ts +242 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +509 -0
- package/dist/native.js.map +1 -0
- package/dist/output.d.ts +166 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +365 -0
- package/dist/output.js.map +1 -0
- package/dist/path.d.ts +420 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +687 -0
- package/dist/path.js.map +1 -0
- package/dist/pdf/object.d.ts +489 -0
- package/dist/pdf/object.d.ts.map +1 -0
- package/dist/pdf/object.js +1045 -0
- package/dist/pdf/object.js.map +1 -0
- package/dist/pixmap.d.ts +315 -0
- package/dist/pixmap.d.ts.map +1 -0
- package/dist/pixmap.js +590 -0
- package/dist/pixmap.js.map +1 -0
- package/dist/profiler.d.ts +159 -0
- package/dist/profiler.d.ts.map +1 -0
- package/dist/profiler.js +380 -0
- package/dist/profiler.js.map +1 -0
- package/dist/render-options.d.ts +227 -0
- package/dist/render-options.d.ts.map +1 -0
- package/dist/render-options.js +130 -0
- package/dist/render-options.js.map +1 -0
- package/dist/resource-tracking.d.ts +332 -0
- package/dist/resource-tracking.d.ts.map +1 -0
- package/dist/resource-tracking.js +653 -0
- package/dist/resource-tracking.js.map +1 -0
- package/dist/simple.d.ts +276 -0
- package/dist/simple.d.ts.map +1 -0
- package/dist/simple.js +343 -0
- package/dist/simple.js.map +1 -0
- package/dist/stext.d.ts +290 -0
- package/dist/stext.d.ts.map +1 -0
- package/dist/stext.js +312 -0
- package/dist/stext.js.map +1 -0
- package/dist/stream.d.ts +174 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +476 -0
- package/dist/stream.js.map +1 -0
- package/dist/text.d.ts +337 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +454 -0
- package/dist/text.js.map +1 -0
- package/dist/typed-arrays.d.ts +127 -0
- package/dist/typed-arrays.d.ts.map +1 -0
- package/dist/typed-arrays.js +410 -0
- package/dist/typed-arrays.js.map +1 -0
- package/dist/types.d.ts +358 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +216 -0
- package/dist/types.js.map +1 -0
- package/native/annot.cc +557 -0
- package/native/buffer.cc +204 -0
- package/native/colorspace.cc +166 -0
- package/native/context.cc +84 -0
- package/native/cookie.cc +179 -0
- package/native/device.cc +179 -0
- package/native/display_list.cc +179 -0
- package/native/document.cc +268 -0
- package/native/enhanced.cc +70 -0
- package/native/font.cc +282 -0
- package/native/form.cc +523 -0
- package/native/geometry.cc +255 -0
- package/native/image.cc +216 -0
- package/native/include/micropdf/enhanced.h +38 -0
- package/native/include/micropdf/types.h +36 -0
- package/native/include/micropdf.h +106 -0
- package/native/include/mupdf-ffi.h +39 -0
- package/native/include/mupdf.h +11 -0
- package/native/include/mupdf_minimal.h +381 -0
- package/native/lib/linux-x64/libmicropdf.a +0 -0
- package/native/link.cc +234 -0
- package/native/micropdf.cc +71 -0
- package/native/output.cc +229 -0
- package/native/page.cc +572 -0
- package/native/path.cc +259 -0
- package/native/pixmap.cc +240 -0
- package/native/stext.cc +610 -0
- package/native/stream.cc +239 -0
- package/package.json +120 -0
- package/scripts/build-from-rust.js +97 -0
- package/scripts/install.js +184 -0
package/native/device.cc
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MicroPDF Device Bindings
|
|
3
|
+
*
|
|
4
|
+
* N-API bindings for device operations.
|
|
5
|
+
* Devices are the destination for rendering operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <napi.h>
|
|
9
|
+
#include "include/mupdf_minimal.h"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a draw device for pixmap rendering
|
|
13
|
+
*
|
|
14
|
+
* @param ctx - Context handle
|
|
15
|
+
* @param pixmap - Pixmap handle
|
|
16
|
+
* @returns Device handle
|
|
17
|
+
*/
|
|
18
|
+
Napi::BigInt NewDrawDevice(const Napi::CallbackInfo& info) {
|
|
19
|
+
Napi::Env env = info.Env();
|
|
20
|
+
|
|
21
|
+
if (info.Length() < 2) {
|
|
22
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, pixmap")
|
|
23
|
+
.ThrowAsJavaScriptException();
|
|
24
|
+
return Napi::BigInt::New(env, static_cast<uint64_t>(0));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
bool lossless;
|
|
28
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
29
|
+
uint64_t pixmap_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
30
|
+
|
|
31
|
+
uint64_t device_handle = fz_new_draw_device(ctx_handle, pixmap_handle);
|
|
32
|
+
|
|
33
|
+
return Napi::BigInt::New(env, device_handle);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a display list device
|
|
38
|
+
*
|
|
39
|
+
* @param ctx - Context handle
|
|
40
|
+
* @param list - Display list handle
|
|
41
|
+
* @returns Device handle
|
|
42
|
+
*/
|
|
43
|
+
Napi::BigInt NewListDevice(const Napi::CallbackInfo& info) {
|
|
44
|
+
Napi::Env env = info.Env();
|
|
45
|
+
|
|
46
|
+
if (info.Length() < 2) {
|
|
47
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, list")
|
|
48
|
+
.ThrowAsJavaScriptException();
|
|
49
|
+
return Napi::BigInt::New(env, static_cast<uint64_t>(0));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
bool lossless;
|
|
53
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
54
|
+
uint64_t list_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
55
|
+
|
|
56
|
+
uint64_t device_handle = fz_new_list_device(ctx_handle, list_handle);
|
|
57
|
+
|
|
58
|
+
return Napi::BigInt::New(env, device_handle);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Drop device handle
|
|
63
|
+
*
|
|
64
|
+
* @param ctx - Context handle
|
|
65
|
+
* @param device - Device handle
|
|
66
|
+
*/
|
|
67
|
+
Napi::Value DropDevice(const Napi::CallbackInfo& info) {
|
|
68
|
+
Napi::Env env = info.Env();
|
|
69
|
+
|
|
70
|
+
if (info.Length() < 2) {
|
|
71
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, device")
|
|
72
|
+
.ThrowAsJavaScriptException();
|
|
73
|
+
return env.Undefined();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
bool lossless;
|
|
77
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
78
|
+
uint64_t device_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
79
|
+
|
|
80
|
+
fz_drop_device(ctx_handle, device_handle);
|
|
81
|
+
|
|
82
|
+
return env.Undefined();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Close device (finish rendering)
|
|
87
|
+
*
|
|
88
|
+
* @param ctx - Context handle
|
|
89
|
+
* @param device - Device handle
|
|
90
|
+
*/
|
|
91
|
+
Napi::Value CloseDevice(const Napi::CallbackInfo& info) {
|
|
92
|
+
Napi::Env env = info.Env();
|
|
93
|
+
|
|
94
|
+
if (info.Length() < 2) {
|
|
95
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, device")
|
|
96
|
+
.ThrowAsJavaScriptException();
|
|
97
|
+
return env.Undefined();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
bool lossless;
|
|
101
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
102
|
+
uint64_t device_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
103
|
+
|
|
104
|
+
fz_close_device(ctx_handle, device_handle);
|
|
105
|
+
|
|
106
|
+
return env.Undefined();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Begin new page on device
|
|
111
|
+
*
|
|
112
|
+
* @param ctx - Context handle
|
|
113
|
+
* @param device - Device handle
|
|
114
|
+
* @param rect - Page rectangle {x0, y0, x1, y1}
|
|
115
|
+
*/
|
|
116
|
+
Napi::Value DeviceBeginPage(const Napi::CallbackInfo& info) {
|
|
117
|
+
Napi::Env env = info.Env();
|
|
118
|
+
|
|
119
|
+
if (info.Length() < 3) {
|
|
120
|
+
Napi::TypeError::New(env, "Expected 3 arguments: ctx, device, rect")
|
|
121
|
+
.ThrowAsJavaScriptException();
|
|
122
|
+
return env.Undefined();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
bool lossless;
|
|
126
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
127
|
+
uint64_t device_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
128
|
+
|
|
129
|
+
Napi::Object rect_obj = info[2].As<Napi::Object>();
|
|
130
|
+
fz_rect rect;
|
|
131
|
+
rect.x0 = rect_obj.Get("x0").As<Napi::Number>().FloatValue();
|
|
132
|
+
rect.y0 = rect_obj.Get("y0").As<Napi::Number>().FloatValue();
|
|
133
|
+
rect.x1 = rect_obj.Get("x1").As<Napi::Number>().FloatValue();
|
|
134
|
+
rect.y1 = rect_obj.Get("y1").As<Napi::Number>().FloatValue();
|
|
135
|
+
|
|
136
|
+
fz_begin_page(ctx_handle, device_handle, rect);
|
|
137
|
+
|
|
138
|
+
return env.Undefined();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* End current page on device
|
|
143
|
+
*
|
|
144
|
+
* @param ctx - Context handle
|
|
145
|
+
* @param device - Device handle
|
|
146
|
+
*/
|
|
147
|
+
Napi::Value DeviceEndPage(const Napi::CallbackInfo& info) {
|
|
148
|
+
Napi::Env env = info.Env();
|
|
149
|
+
|
|
150
|
+
if (info.Length() < 2) {
|
|
151
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, device")
|
|
152
|
+
.ThrowAsJavaScriptException();
|
|
153
|
+
return env.Undefined();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
bool lossless;
|
|
157
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
158
|
+
uint64_t device_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
159
|
+
|
|
160
|
+
fz_end_page(ctx_handle, device_handle);
|
|
161
|
+
|
|
162
|
+
return env.Undefined();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Initialize Device module exports
|
|
167
|
+
*/
|
|
168
|
+
Napi::Object InitDevice(Napi::Env env, Napi::Object exports) {
|
|
169
|
+
exports.Set("newDrawDevice", Napi::Function::New(env, NewDrawDevice));
|
|
170
|
+
exports.Set("newListDevice", Napi::Function::New(env, NewListDevice));
|
|
171
|
+
exports.Set("dropDevice", Napi::Function::New(env, DropDevice));
|
|
172
|
+
exports.Set("closeDevice", Napi::Function::New(env, CloseDevice));
|
|
173
|
+
exports.Set("deviceBeginPage", Napi::Function::New(env, DeviceBeginPage));
|
|
174
|
+
exports.Set("deviceEndPage", Napi::Function::New(env, DeviceEndPage));
|
|
175
|
+
|
|
176
|
+
return exports;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MicroPDF Display List Bindings
|
|
3
|
+
*
|
|
4
|
+
* N-API bindings for PDF display list operations.
|
|
5
|
+
* Display lists cache rendering commands for efficient repeated rendering.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <napi.h>
|
|
9
|
+
#include "include/mupdf_minimal.h"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a new display list
|
|
13
|
+
*
|
|
14
|
+
* @param ctx - Context handle
|
|
15
|
+
* @param rect - Bounding rectangle {x0, y0, x1, y1}
|
|
16
|
+
* @returns Display list handle
|
|
17
|
+
*/
|
|
18
|
+
Napi::BigInt NewDisplayList(const Napi::CallbackInfo& info) {
|
|
19
|
+
Napi::Env env = info.Env();
|
|
20
|
+
|
|
21
|
+
if (info.Length() < 2) {
|
|
22
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, rect")
|
|
23
|
+
.ThrowAsJavaScriptException();
|
|
24
|
+
return Napi::BigInt::New(env, static_cast<uint64_t>(0));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
bool lossless;
|
|
28
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
29
|
+
|
|
30
|
+
Napi::Object rect_obj = info[1].As<Napi::Object>();
|
|
31
|
+
fz_rect rect;
|
|
32
|
+
rect.x0 = rect_obj.Get("x0").As<Napi::Number>().FloatValue();
|
|
33
|
+
rect.y0 = rect_obj.Get("y0").As<Napi::Number>().FloatValue();
|
|
34
|
+
rect.x1 = rect_obj.Get("x1").As<Napi::Number>().FloatValue();
|
|
35
|
+
rect.y1 = rect_obj.Get("y1").As<Napi::Number>().FloatValue();
|
|
36
|
+
|
|
37
|
+
uint64_t list_handle = fz_new_display_list(ctx_handle, rect);
|
|
38
|
+
|
|
39
|
+
return Napi::BigInt::New(env, list_handle);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Drop display list handle
|
|
44
|
+
*
|
|
45
|
+
* @param ctx - Context handle
|
|
46
|
+
* @param list - Display list handle
|
|
47
|
+
*/
|
|
48
|
+
Napi::Value DropDisplayList(const Napi::CallbackInfo& info) {
|
|
49
|
+
Napi::Env env = info.Env();
|
|
50
|
+
|
|
51
|
+
if (info.Length() < 2) {
|
|
52
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, list")
|
|
53
|
+
.ThrowAsJavaScriptException();
|
|
54
|
+
return env.Undefined();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bool lossless;
|
|
58
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
59
|
+
uint64_t list_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
60
|
+
|
|
61
|
+
fz_drop_display_list(ctx_handle, list_handle);
|
|
62
|
+
|
|
63
|
+
return env.Undefined();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get display list bounds
|
|
68
|
+
*
|
|
69
|
+
* @param ctx - Context handle
|
|
70
|
+
* @param list - Display list handle
|
|
71
|
+
* @returns Rectangle {x0, y0, x1, y1}
|
|
72
|
+
*/
|
|
73
|
+
Napi::Object GetDisplayListBounds(const Napi::CallbackInfo& info) {
|
|
74
|
+
Napi::Env env = info.Env();
|
|
75
|
+
Napi::Object rect = Napi::Object::New(env);
|
|
76
|
+
|
|
77
|
+
if (info.Length() < 2) {
|
|
78
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, list")
|
|
79
|
+
.ThrowAsJavaScriptException();
|
|
80
|
+
return rect;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bool lossless;
|
|
84
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
85
|
+
uint64_t list_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
86
|
+
|
|
87
|
+
fz_rect bounds = fz_bound_display_list(ctx_handle, list_handle);
|
|
88
|
+
|
|
89
|
+
rect.Set("x0", Napi::Number::New(env, bounds.x0));
|
|
90
|
+
rect.Set("y0", Napi::Number::New(env, bounds.y0));
|
|
91
|
+
rect.Set("x1", Napi::Number::New(env, bounds.x1));
|
|
92
|
+
rect.Set("y1", Napi::Number::New(env, bounds.y1));
|
|
93
|
+
|
|
94
|
+
return rect;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Run display list on device
|
|
99
|
+
*
|
|
100
|
+
* @param ctx - Context handle
|
|
101
|
+
* @param list - Display list handle
|
|
102
|
+
* @param device - Device handle
|
|
103
|
+
* @param matrix - Transform matrix {a, b, c, d, e, f}
|
|
104
|
+
* @param rect - Clipping rectangle {x0, y0, x1, y1}
|
|
105
|
+
*/
|
|
106
|
+
Napi::Value RunDisplayList(const Napi::CallbackInfo& info) {
|
|
107
|
+
Napi::Env env = info.Env();
|
|
108
|
+
|
|
109
|
+
if (info.Length() < 5) {
|
|
110
|
+
Napi::TypeError::New(env, "Expected 5 arguments: ctx, list, device, matrix, rect")
|
|
111
|
+
.ThrowAsJavaScriptException();
|
|
112
|
+
return env.Undefined();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool lossless;
|
|
116
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
117
|
+
uint64_t list_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
118
|
+
uint64_t device_handle = info[2].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
119
|
+
|
|
120
|
+
Napi::Object matrix_obj = info[3].As<Napi::Object>();
|
|
121
|
+
fz_matrix matrix;
|
|
122
|
+
matrix.a = matrix_obj.Get("a").As<Napi::Number>().FloatValue();
|
|
123
|
+
matrix.b = matrix_obj.Get("b").As<Napi::Number>().FloatValue();
|
|
124
|
+
matrix.c = matrix_obj.Get("c").As<Napi::Number>().FloatValue();
|
|
125
|
+
matrix.d = matrix_obj.Get("d").As<Napi::Number>().FloatValue();
|
|
126
|
+
matrix.e = matrix_obj.Get("e").As<Napi::Number>().FloatValue();
|
|
127
|
+
matrix.f = matrix_obj.Get("f").As<Napi::Number>().FloatValue();
|
|
128
|
+
|
|
129
|
+
Napi::Object rect_obj = info[4].As<Napi::Object>();
|
|
130
|
+
fz_rect rect;
|
|
131
|
+
rect.x0 = rect_obj.Get("x0").As<Napi::Number>().FloatValue();
|
|
132
|
+
rect.y0 = rect_obj.Get("y0").As<Napi::Number>().FloatValue();
|
|
133
|
+
rect.x1 = rect_obj.Get("x1").As<Napi::Number>().FloatValue();
|
|
134
|
+
rect.y1 = rect_obj.Get("y1").As<Napi::Number>().FloatValue();
|
|
135
|
+
|
|
136
|
+
fz_run_display_list(ctx_handle, list_handle, device_handle, matrix, rect);
|
|
137
|
+
|
|
138
|
+
return env.Undefined();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Create display list from page
|
|
143
|
+
*
|
|
144
|
+
* @param ctx - Context handle
|
|
145
|
+
* @param page - Page handle
|
|
146
|
+
* @returns Display list handle
|
|
147
|
+
*/
|
|
148
|
+
Napi::BigInt NewDisplayListFromPage(const Napi::CallbackInfo& info) {
|
|
149
|
+
Napi::Env env = info.Env();
|
|
150
|
+
|
|
151
|
+
if (info.Length() < 2) {
|
|
152
|
+
Napi::TypeError::New(env, "Expected 2 arguments: ctx, page")
|
|
153
|
+
.ThrowAsJavaScriptException();
|
|
154
|
+
return Napi::BigInt::New(env, static_cast<uint64_t>(0));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
bool lossless;
|
|
158
|
+
uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
159
|
+
uint64_t page_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
|
|
160
|
+
|
|
161
|
+
uint64_t list_handle = fz_new_display_list_from_page(ctx_handle, page_handle);
|
|
162
|
+
|
|
163
|
+
return Napi::BigInt::New(env, list_handle);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Initialize DisplayList module exports
|
|
168
|
+
*/
|
|
169
|
+
Napi::Object InitDisplayList(Napi::Env env, Napi::Object exports) {
|
|
170
|
+
exports.Set("newDisplayList", Napi::Function::New(env, NewDisplayList));
|
|
171
|
+
exports.Set("dropDisplayList", Napi::Function::New(env, DropDisplayList));
|
|
172
|
+
exports.Set("getDisplayListBounds", Napi::Function::New(env, GetDisplayListBounds));
|
|
173
|
+
exports.Set("runDisplayList", Napi::Function::New(env, RunDisplayList));
|
|
174
|
+
exports.Set("newDisplayListFromPage", Napi::Function::New(env, NewDisplayListFromPage));
|
|
175
|
+
|
|
176
|
+
return exports;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document FFI Bindings
|
|
3
|
+
*
|
|
4
|
+
* Implements N-API bindings for PDF document functions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <napi.h>
|
|
8
|
+
#include "include/mupdf_minimal.h"
|
|
9
|
+
#include <cstring>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper: Extract context from object
|
|
13
|
+
*/
|
|
14
|
+
static fz_context GetContext(const Napi::Object& obj) {
|
|
15
|
+
return obj.Get("_handle").As<Napi::Number>().Int32Value();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper: Extract document handle from object
|
|
20
|
+
*/
|
|
21
|
+
static fz_document GetDocument(const Napi::Object& obj) {
|
|
22
|
+
return obj.Get("_handle").As<Napi::Number>().Int32Value();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Open document from file path
|
|
27
|
+
* JavaScript: openDocumentFromPath(ctx: NativeContext, path: string): NativeDocument
|
|
28
|
+
*/
|
|
29
|
+
Napi::Value OpenDocumentFromPath(const Napi::CallbackInfo& info) {
|
|
30
|
+
Napi::Env env = info.Env();
|
|
31
|
+
|
|
32
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsString()) {
|
|
33
|
+
Napi::TypeError::New(env, "Expected (context, path)").ThrowAsJavaScriptException();
|
|
34
|
+
return env.Null();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
38
|
+
std::string path = info[1].As<Napi::String>().Utf8Value();
|
|
39
|
+
|
|
40
|
+
fz_document doc = fz_open_document(ctx, path.c_str());
|
|
41
|
+
if (doc == 0) {
|
|
42
|
+
Napi::Error::New(env, "Failed to open document").ThrowAsJavaScriptException();
|
|
43
|
+
return env.Null();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
47
|
+
obj.Set("_handle", Napi::Number::New(env, doc));
|
|
48
|
+
return obj;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Open document from memory buffer
|
|
53
|
+
* JavaScript: openDocument(ctx: NativeContext, data: Buffer, magic: string): NativeDocument
|
|
54
|
+
*/
|
|
55
|
+
Napi::Value OpenDocument(const Napi::CallbackInfo& info) {
|
|
56
|
+
Napi::Env env = info.Env();
|
|
57
|
+
|
|
58
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsBuffer() || !info[2].IsString()) {
|
|
59
|
+
Napi::TypeError::New(env, "Expected (context, buffer, magic)").ThrowAsJavaScriptException();
|
|
60
|
+
return env.Null();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
64
|
+
Napi::Buffer<uint8_t> buffer = info[1].As<Napi::Buffer<uint8_t>>();
|
|
65
|
+
std::string magic = info[2].As<Napi::String>().Utf8Value();
|
|
66
|
+
|
|
67
|
+
fz_document doc = fz_open_document_with_buffer(ctx, magic.c_str(), buffer.Data(), buffer.Length());
|
|
68
|
+
if (doc == 0) {
|
|
69
|
+
Napi::Error::New(env, "Failed to open document").ThrowAsJavaScriptException();
|
|
70
|
+
return env.Null();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
74
|
+
obj.Set("_handle", Napi::Number::New(env, doc));
|
|
75
|
+
return obj;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Drop/free a document
|
|
80
|
+
* JavaScript: dropDocument(ctx: NativeContext, doc: NativeDocument): void
|
|
81
|
+
*/
|
|
82
|
+
Napi::Value DropDocument(const Napi::CallbackInfo& info) {
|
|
83
|
+
Napi::Env env = info.Env();
|
|
84
|
+
|
|
85
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject()) {
|
|
86
|
+
Napi::TypeError::New(env, "Expected (context, document)").ThrowAsJavaScriptException();
|
|
87
|
+
return env.Undefined();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
91
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
92
|
+
|
|
93
|
+
fz_drop_document(ctx, doc);
|
|
94
|
+
|
|
95
|
+
return env.Undefined();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Count pages in document
|
|
100
|
+
* JavaScript: countPages(ctx: NativeContext, doc: NativeDocument): number
|
|
101
|
+
*/
|
|
102
|
+
Napi::Value CountPages(const Napi::CallbackInfo& info) {
|
|
103
|
+
Napi::Env env = info.Env();
|
|
104
|
+
|
|
105
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject()) {
|
|
106
|
+
Napi::TypeError::New(env, "Expected (context, document)").ThrowAsJavaScriptException();
|
|
107
|
+
return env.Null();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
111
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
112
|
+
|
|
113
|
+
int count = fz_count_pages(ctx, doc);
|
|
114
|
+
|
|
115
|
+
return Napi::Number::New(env, count);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Check if document needs password
|
|
120
|
+
* JavaScript: needsPassword(ctx: NativeContext, doc: NativeDocument): boolean
|
|
121
|
+
*/
|
|
122
|
+
Napi::Value NeedsPassword(const Napi::CallbackInfo& info) {
|
|
123
|
+
Napi::Env env = info.Env();
|
|
124
|
+
|
|
125
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject()) {
|
|
126
|
+
Napi::TypeError::New(env, "Expected (context, document)").ThrowAsJavaScriptException();
|
|
127
|
+
return env.Null();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
131
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
132
|
+
|
|
133
|
+
int needs = fz_needs_password(ctx, doc);
|
|
134
|
+
|
|
135
|
+
return Napi::Boolean::New(env, needs != 0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Authenticate document with password
|
|
140
|
+
* JavaScript: authenticatePassword(ctx: NativeContext, doc: NativeDocument, password: string): boolean
|
|
141
|
+
*/
|
|
142
|
+
Napi::Value AuthenticatePassword(const Napi::CallbackInfo& info) {
|
|
143
|
+
Napi::Env env = info.Env();
|
|
144
|
+
|
|
145
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsObject() || !info[2].IsString()) {
|
|
146
|
+
Napi::TypeError::New(env, "Expected (context, document, password)").ThrowAsJavaScriptException();
|
|
147
|
+
return env.Null();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
151
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
152
|
+
std::string password = info[2].As<Napi::String>().Utf8Value();
|
|
153
|
+
|
|
154
|
+
int success = fz_authenticate_password(ctx, doc, password.c_str());
|
|
155
|
+
|
|
156
|
+
return Napi::Boolean::New(env, success != 0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Check document permission
|
|
161
|
+
* JavaScript: hasPermission(ctx: NativeContext, doc: NativeDocument, permission: number): boolean
|
|
162
|
+
*/
|
|
163
|
+
Napi::Value HasPermission(const Napi::CallbackInfo& info) {
|
|
164
|
+
Napi::Env env = info.Env();
|
|
165
|
+
|
|
166
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsObject() || !info[2].IsNumber()) {
|
|
167
|
+
Napi::TypeError::New(env, "Expected (context, document, permission)").ThrowAsJavaScriptException();
|
|
168
|
+
return env.Null();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
172
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
173
|
+
int permission = info[2].As<Napi::Number>().Int32Value();
|
|
174
|
+
|
|
175
|
+
int has = fz_has_permission(ctx, doc, permission);
|
|
176
|
+
|
|
177
|
+
return Napi::Boolean::New(env, has != 0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get document metadata
|
|
182
|
+
* JavaScript: getMetadata(ctx: NativeContext, doc: NativeDocument, key: string): string | null
|
|
183
|
+
*/
|
|
184
|
+
Napi::Value GetMetadata(const Napi::CallbackInfo& info) {
|
|
185
|
+
Napi::Env env = info.Env();
|
|
186
|
+
|
|
187
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsObject() || !info[2].IsString()) {
|
|
188
|
+
Napi::TypeError::New(env, "Expected (context, document, key)").ThrowAsJavaScriptException();
|
|
189
|
+
return env.Null();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
193
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
194
|
+
std::string key = info[2].As<Napi::String>().Utf8Value();
|
|
195
|
+
|
|
196
|
+
char buf[1024] = {0};
|
|
197
|
+
int len = fz_lookup_metadata(ctx, doc, key.c_str(), buf, sizeof(buf));
|
|
198
|
+
|
|
199
|
+
if (len > 0) {
|
|
200
|
+
return Napi::String::New(env, buf);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return env.Null();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Save document to file
|
|
208
|
+
* JavaScript: saveDocument(ctx: NativeContext, doc: NativeDocument, path: string): void
|
|
209
|
+
*/
|
|
210
|
+
Napi::Value SaveDocument(const Napi::CallbackInfo& info) {
|
|
211
|
+
Napi::Env env = info.Env();
|
|
212
|
+
|
|
213
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsObject() || !info[2].IsString()) {
|
|
214
|
+
Napi::TypeError::New(env, "Expected (context, document, path)").ThrowAsJavaScriptException();
|
|
215
|
+
return env.Undefined();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
219
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
220
|
+
std::string path = info[2].As<Napi::String>().Utf8Value();
|
|
221
|
+
|
|
222
|
+
pdf_save_document(ctx, doc, path.c_str(), nullptr);
|
|
223
|
+
|
|
224
|
+
return env.Undefined();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Resolve named destination
|
|
229
|
+
* JavaScript: resolveLink(ctx: NativeContext, doc: NativeDocument, name: string): number | null
|
|
230
|
+
*/
|
|
231
|
+
Napi::Value ResolveLink(const Napi::CallbackInfo& info) {
|
|
232
|
+
Napi::Env env = info.Env();
|
|
233
|
+
|
|
234
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsObject() || !info[2].IsString()) {
|
|
235
|
+
Napi::TypeError::New(env, "Expected (context, document, name)").ThrowAsJavaScriptException();
|
|
236
|
+
return env.Null();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
fz_context ctx = GetContext(info[0].As<Napi::Object>());
|
|
240
|
+
fz_document doc = GetDocument(info[1].As<Napi::Object>());
|
|
241
|
+
std::string name = info[2].As<Napi::String>().Utf8Value();
|
|
242
|
+
|
|
243
|
+
int page = pdf_lookup_named_dest(ctx, doc, name.c_str());
|
|
244
|
+
|
|
245
|
+
if (page >= 0) {
|
|
246
|
+
return Napi::Number::New(env, page);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return env.Null();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Initialize document exports
|
|
254
|
+
*/
|
|
255
|
+
Napi::Object InitDocument(Napi::Env env, Napi::Object exports) {
|
|
256
|
+
exports.Set("openDocumentFromPath", Napi::Function::New(env, OpenDocumentFromPath));
|
|
257
|
+
exports.Set("openDocument", Napi::Function::New(env, OpenDocument));
|
|
258
|
+
exports.Set("dropDocument", Napi::Function::New(env, DropDocument));
|
|
259
|
+
exports.Set("countPages", Napi::Function::New(env, CountPages));
|
|
260
|
+
exports.Set("needsPassword", Napi::Function::New(env, NeedsPassword));
|
|
261
|
+
exports.Set("authenticatePassword", Napi::Function::New(env, AuthenticatePassword));
|
|
262
|
+
exports.Set("hasPermission", Napi::Function::New(env, HasPermission));
|
|
263
|
+
exports.Set("getMetadata", Napi::Function::New(env, GetMetadata));
|
|
264
|
+
exports.Set("saveDocument", Napi::Function::New(env, SaveDocument));
|
|
265
|
+
exports.Set("resolveLink", Napi::Function::New(env, ResolveLink));
|
|
266
|
+
return exports;
|
|
267
|
+
}
|
|
268
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced API FFI Bindings
|
|
3
|
+
*
|
|
4
|
+
* Implements N-API bindings for MicroPDF-specific enhanced functions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <napi.h>
|
|
8
|
+
#include "include/micropdf/enhanced.h"
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <cstring>
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Helper: Extract context handle from object
|
|
14
|
+
*/
|
|
15
|
+
static int32_t GetContext(const Napi::Object& obj) {
|
|
16
|
+
return obj.Get("_handle").As<Napi::Number>().Int32Value();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Merge multiple PDFs into one output PDF
|
|
21
|
+
* JavaScript: npMergePDFs(ctx: NativeContext, paths: string[], count: number, outputPath: string): number
|
|
22
|
+
*/
|
|
23
|
+
Napi::Value MergePDFs(const Napi::CallbackInfo& info) {
|
|
24
|
+
Napi::Env env = info.Env();
|
|
25
|
+
|
|
26
|
+
if (info.Length() < 4 ||
|
|
27
|
+
!info[0].IsObject() ||
|
|
28
|
+
!info[1].IsArray() ||
|
|
29
|
+
!info[2].IsNumber() ||
|
|
30
|
+
!info[3].IsString()) {
|
|
31
|
+
Napi::TypeError::New(env, "Expected (context, paths: string[], count: number, outputPath: string)")
|
|
32
|
+
.ThrowAsJavaScriptException();
|
|
33
|
+
return Napi::Number::New(env, -1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
int32_t ctx = GetContext(info[0].As<Napi::Object>());
|
|
37
|
+
Napi::Array pathsArray = info[1].As<Napi::Array>();
|
|
38
|
+
int32_t count = info[2].As<Napi::Number>().Int32Value();
|
|
39
|
+
std::string outputPath = info[3].As<Napi::String>().Utf8Value();
|
|
40
|
+
|
|
41
|
+
// Convert JavaScript string array to C string array
|
|
42
|
+
std::vector<const char*> paths(count);
|
|
43
|
+
std::vector<std::string> pathStrings(count);
|
|
44
|
+
|
|
45
|
+
for (int32_t i = 0; i < count; i++) {
|
|
46
|
+
Napi::Value val = pathsArray[i];
|
|
47
|
+
if (!val.IsString()) {
|
|
48
|
+
Napi::TypeError::New(env, "All paths must be strings")
|
|
49
|
+
.ThrowAsJavaScriptException();
|
|
50
|
+
return Napi::Number::New(env, -1);
|
|
51
|
+
}
|
|
52
|
+
pathStrings[i] = val.As<Napi::String>().Utf8Value();
|
|
53
|
+
paths[i] = pathStrings[i].c_str();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Call the Rust FFI function
|
|
57
|
+
int32_t result = mp_merge_pdfs(ctx, paths.data(), count, outputPath.c_str());
|
|
58
|
+
|
|
59
|
+
return Napi::Number::New(env, result);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Initialize enhanced API exports
|
|
64
|
+
*/
|
|
65
|
+
Napi::Object InitEnhanced(Napi::Env env, Napi::Object exports) {
|
|
66
|
+
exports.Set("npMergePDFs", Napi::Function::New(env, MergePDFs));
|
|
67
|
+
|
|
68
|
+
return exports;
|
|
69
|
+
}
|
|
70
|
+
|