Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
/*
2
* mjs test file generation tool
3
*/
4
5
#include "mupdf/fitz.h"
6
#include "mupdf/pdf.h"
7
8
/*
9
A useful bit of bash script to call this to generate mjs files:
10
for f in tests_private/pdf/forms/v1.3/ *.pdf ; do g=${f%.*} ; echo $g ; ./mjsgen $g.pdf $g.mjs ; done
11
12
Remove the space from "/ *.pdf" before running - can't leave that
13
in here, as it causes a warning about a possibly malformed comment.
14
*/
15
16
static char lorem[] =
17
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum "
18
"vehicula augue id est lobortis mollis. Aenean vestibulum metus sed est "
19
"gravida non tempus lacus aliquet. Nulla vehicula lobortis tincidunt. "
20
"Donec malesuada nisl et lacus condimentum nec tincidunt urna gravida. "
21
"Sed dapibus magna eu velit ultrices non rhoncus risus lacinia. Fusce "
22
"vitae nulla volutpat elit dictum ornare at eu libero. Maecenas felis "
23
"enim, tempor a tincidunt id, commodo consequat lectus.\n"
24
"Morbi tincidunt adipiscing lacus eu dignissim. Pellentesque augue elit, "
25
"ultrices vitae fermentum et, faucibus et purus. Nam ante libero, lacinia "
26
"id tincidunt at, ultricies a lorem. Donec non neque at purus condimentum "
27
"eleifend quis sit amet libero. Sed semper, mi ut tempus tincidunt, lacus "
28
"eros pellentesque lacus, id vehicula est diam eu quam. Integer tristique "
29
"fringilla rhoncus. Phasellus convallis, justo ut mollis viverra, dui odio "
30
"euismod ante, nec fringilla nisl mi ac diam.\n"
31
"Maecenas mi urna, ornare commodo feugiat id, cursus in massa. Vivamus "
32
"augue augue, aliquam at varius eu, venenatis fermentum felis. Sed varius "
33
"turpis a felis ultrices quis aliquet nunc tincidunt. Suspendisse posuere "
34
"commodo nunc non viverra. Praesent condimentum varius quam, vel "
35
"consectetur odio volutpat in. Sed malesuada augue ut lectus commodo porta. "
36
"Vivamus eget mauris sit amet diam ultrices sollicitudin. Cras pharetra leo "
37
"non elit lacinia vulputate.\n"
38
"Donec ac enim justo, ornare scelerisque diam. Ut vel ante at lorem "
39
"placerat bibendum ultricies mattis metus. Phasellus in imperdiet odio. "
40
"Proin semper lacinia libero, sed rutrum eros blandit non. Duis tincidunt "
41
"ligula est, non pellentesque mauris. Aliquam in erat scelerisque lacus "
42
"dictum suscipit eget semper magna. Nullam luctus imperdiet risus a "
43
"semper.\n"
44
"Curabitur sit amet tempor sapien. Quisque et tortor in lacus dictum "
45
"pulvinar. Nunc at nisl ut velit vehicula hendrerit. Mauris elementum "
46
"sollicitudin leo ac ullamcorper. Proin vel leo nec justo tempus aliquet "
47
"nec ut mi. Pellentesque vel nisl id dui hendrerit fermentum nec quis "
48
"tortor. Proin eu sem luctus est consequat euismod. Vestibulum ante ipsum "
49
"primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce "
50
"consectetur ultricies nisl ornare dictum. Cras sagittis consectetur lorem "
51
"sed posuere. Mauris accumsan laoreet arcu, id molestie lorem faucibus eu. "
52
"Vivamus commodo, neque nec imperdiet pretium, lorem metus viverra turpis, "
53
"malesuada vulputate justo eros sit amet neque. Nunc quis justo elit, non "
54
"rutrum mauris. Maecenas blandit condimentum nibh, nec vulputate orci "
55
"pulvinar at. Proin sed arcu vel odio tempus lobortis sed posuere ipsum. Ut "
56
"feugiat pellentesque tortor nec ornare.\n";
57
58
static char *filename;
59
fz_output *out = NULL;
60
61
static char *mujstest_filename = NULL;
62
static FILE *mujstest_file = NULL;
63
static int mujstest_count = 0;
64
65
static void usage(void)
66
{
67
fprintf(stderr, "usage: mjsgen [-p password] input.pdf output.mjs\n");
68
exit(1);
69
}
70
71
static void escape_string(FILE *out, int len, const char *string)
72
{
73
while (len-- && *string)
74
{
75
char c = *string++;
76
switch (c)
77
{
78
case '\n':
79
fputc('\\', out);
80
fputc('n', out);
81
break;
82
case '\r':
83
fputc('\\', out);
84
fputc('r', out);
85
break;
86
case '\t':
87
fputc('\\', out);
88
fputc('t', out);
89
break;
90
default:
91
fputc(c, out);
92
}
93
}
94
}
95
96
static void processpage(fz_context *ctx, fz_document *doc, int pagenum)
97
{
98
fz_page *page;
99
int needshot = 0;
100
101
fz_try(ctx)
102
{
103
page = fz_load_page(ctx, doc, pagenum - 1);
104
}
105
fz_catch(ctx)
106
{
107
fz_rethrow_message(ctx, "cannot load page %d in file '%s'", pagenum, filename);
108
}
109
110
pdf_document *inter = pdf_specifics(ctx, doc);
111
pdf_widget *widget = NULL;
112
113
if (inter)
114
widget = pdf_first_widget(inter, (pdf_page *)page);
115
116
if (widget)
117
{
118
fprintf(mujstest_file, "GOTO %d\n", pagenum);
119
needshot = 1;
120
}
121
for (;widget; widget = pdf_next_widget(widget))
122
{
123
fz_rect rect;
124
int w, h, len;
125
int type = pdf_widget_get_type(widget);
126
127
pdf_bound_widget(widget, &rect);
128
w = (rect.x1 - rect.x0);
129
h = (rect.y1 - rect.y0);
130
++mujstest_count;
131
switch (type)
132
{
133
default:
134
fprintf(mujstest_file, "%% UNKNOWN %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
135
break;
136
case PDF_WIDGET_TYPE_PUSHBUTTON:
137
fprintf(mujstest_file, "%% PUSHBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
138
break;
139
case PDF_WIDGET_TYPE_CHECKBOX:
140
fprintf(mujstest_file, "%% CHECKBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
141
break;
142
case PDF_WIDGET_TYPE_RADIOBUTTON:
143
fprintf(mujstest_file, "%% RADIOBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
144
break;
145
case PDF_WIDGET_TYPE_TEXT:
146
{
147
int maxlen = pdf_text_widget_max_len(inter, widget);
148
int texttype = pdf_text_widget_content_type(inter, widget);
149
150
/* If height is low, assume a single row, and base
151
* the width off that. */
152
if (h < 10)
153
{
154
w = (w+h-1) / (h ? h : 1);
155
h = 1;
156
}
157
/* Otherwise, if width is low, work off height */
158
else if (w < 10)
159
{
160
h = (w+h-1) / (w ? w : 1);
161
w = 1;
162
}
163
else
164
{
165
w = (w+9)/10;
166
h = (h+9)/10;
167
}
168
len = w*h;
169
if (len < 2)
170
len = 2;
171
if (len > maxlen)
172
len = maxlen;
173
fprintf(mujstest_file, "%% TEXT %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
174
switch (texttype)
175
{
176
default:
177
case PDF_WIDGET_CONTENT_UNRESTRAINED:
178
fprintf(mujstest_file, "TEXT %d ", mujstest_count);
179
escape_string(mujstest_file, len-3, lorem);
180
fprintf(mujstest_file, "\n");
181
break;
182
case PDF_WIDGET_CONTENT_NUMBER:
183
fprintf(mujstest_file, "TEXT %d\n", mujstest_count);
184
break;
185
case PDF_WIDGET_CONTENT_SPECIAL:
186
#ifdef __MINGW32__
187
fprintf(mujstest_file, "TEXT %I64d\n", 46702919800LL + mujstest_count);
188
#else
189
fprintf(mujstest_file, "TEXT %lld\n", 46702919800LL + mujstest_count);
190
#endif
191
break;
192
case PDF_WIDGET_CONTENT_DATE:
193
fprintf(mujstest_file, "TEXT Jun %d 1979\n", 1 + ((13 + mujstest_count) % 30));
194
break;
195
case PDF_WIDGET_CONTENT_TIME:
196
++mujstest_count;
197
fprintf(mujstest_file, "TEXT %02d:%02d\n", ((mujstest_count/60) % 24), mujstest_count % 60);
198
break;
199
}
200
break;
201
}
202
case PDF_WIDGET_TYPE_LISTBOX:
203
fprintf(mujstest_file, "%% LISTBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
204
break;
205
case PDF_WIDGET_TYPE_COMBOBOX:
206
fprintf(mujstest_file, "%% COMBOBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1);
207
break;
208
}
209
fprintf(mujstest_file, "CLICK %0.2f %0.2f\n", (rect.x0+rect.x1)/2, (rect.y0+rect.y1)/2);
210
}
211
212
fz_flush_warnings(ctx);
213
214
if (mujstest_file && needshot)
215
{
216
fprintf(mujstest_file, "SCREENSHOT\n");
217
}
218
}
219
220
static void processpages(fz_context *ctx, fz_document *doc)
221
{
222
int page, pagecount;
223
pagecount = fz_count_pages(ctx, doc);
224
for (page = 1; page <= pagecount; ++page)
225
processpage(ctx, doc, page);
226
}
227
228
int main(int argc, char **argv)
229
{
230
char *password = "";
231
fz_document *doc = NULL;
232
fz_context *ctx;
233
int c;
234
235
fz_var(ctx, doc);
236
237
while ((c = fz_getopt(argc, argv, "p:")) != -1)
238
{
239
switch (c)
240
{
241
default: usage(); break;
242
case 'p': password = fz_optarg; break;
243
}
244
}
245
246
if (fz_optind + 2 != argc)
247
usage();
248
249
filename = argv[fz_optind];
250
mujstest_filename = argv[fz_optind+1];
251
252
if (strcmp(mujstest_filename, "-") == 0)
253
mujstest_file = stdout;
254
else
255
mujstest_file = fopen(mujstest_filename, "wb");
256
257
ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
258
if (!ctx)
259
{
260
fprintf(stderr, "cannot initialise context\n");
261
exit(1);
262
}
263
264
fz_register_document_handlers(ctx);
265
266
fz_try(ctx)
267
{
268
doc = fz_open_document(ctx, filename);
269
270
if (fz_needs_password(doc))
271
{
272
if (!fz_authenticate_password(ctx, doc, password))
273
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", filename);
274
fprintf(mujstest_file, "PASSWORD %s\n", password);
275
}
276
277
fprintf(mujstest_file, "OPEN %s\n", filename);
278
279
processpages(ctx, doc);
280
281
fz_drop_document(ctx, doc);
282
}
283
fz_catch(ctx)
284
{
285
fprintf(stderr, "mjsgen: cannot process document: %s\n", filename);
286
return 1;
287
}
288
289
fclose(mujstest_file);
290
fz_drop_context(ctx);
291
return 0;
292
}
293
294
#ifdef _MSC_VER
295
int wmain(int argc, wchar_t *wargv[])
296
{
297
char **argv = fz_argv_from_wargv(argc, wargv);
298
int ret = main(argc, argv);
299
fz_free_argv(argc, argv);
300
return ret;
301
}
302
#endif
303
304