1 /* lpdflib.c
2
3 Copyright 2006-2011 Taco Hoekwater <taco@luatex.org>
4
5 This file is part of LuaTeX.
6
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
19
20
21 #include "ptexlib.h"
22 #include "lua/luatex-api.h"
23
luapdfprint(lua_State * L)24 static int luapdfprint(lua_State * L)
25 {
26 int n;
27 const_lstring st;
28 const char *modestr_s;
29 ctm_transform_modes literal_mode;
30 st.s = modestr_s = NULL;
31 n = lua_gettop(L);
32 if (!lua_isstring(L, -1)) {
33 luaL_error(L, "no string to print");
34 }
35 literal_mode = set_origin;
36 if (n == 2) {
37 if (!lua_isstring(L, -2)) {
38 luaL_error(L, "invalid argument for print literal mode");
39 } else {
40 modestr_s = lua_tostring(L, -2);
41 if (lua_key_eq(modestr_s,direct))
42 literal_mode = direct_always;
43 else if (lua_key_eq(modestr_s,page))
44 literal_mode = direct_page;
45 else {
46 luaL_error(L, "invalid argument for print literal mode");
47 }
48 }
49 } else {
50 if (n != 1) {
51 luaL_error(L, "invalid number of arguments");
52 }
53 }
54 check_o_mode(static_pdf, "pdf.print()", 1 << OMODE_PDF, true);
55 switch (literal_mode) {
56 case (set_origin):
57 pdf_goto_pagemode(static_pdf);
58 pdf_set_pos(static_pdf, static_pdf->posstruct->pos);
59 (void) calc_pdfpos(static_pdf->pstruct, static_pdf->posstruct->pos);
60 break;
61 case (direct_page):
62 pdf_goto_pagemode(static_pdf);
63 (void) calc_pdfpos(static_pdf->pstruct, static_pdf->posstruct->pos);
64 break;
65 case (direct_always):
66 pdf_end_string_nl(static_pdf);
67 break;
68 default:
69 assert(0);
70 }
71 st.s = lua_tolstring(L, n, &st.l);
72 pdf_out_block(static_pdf, st.s, st.l);
73 return 0;
74 }
75
fread_to_buf(lua_State * L,const char * filename,size_t * len)76 static unsigned char *fread_to_buf(lua_State * L, const char *filename,
77 size_t * len)
78 {
79 int ilen = 0;
80 FILE *f;
81 unsigned char *buf = NULL;
82 if ((f = fopen(filename, "rb")) == NULL)
83 luaL_error(L, "pdf.immediateobj() cannot open input file");
84 if (readbinfile(f, &buf, &ilen) == 0)
85 luaL_error(L, "pdf.immediateobj() cannot read input file");
86 fclose(f);
87 *len = (size_t) ilen;
88 return buf;
89 }
90
l_immediateobj(lua_State * L)91 static int l_immediateobj(lua_State * L)
92 {
93 int n, first_arg = 1;
94 int k;
95 lstring buf;
96 const_lstring st1,st2, st3;
97 const char *st1_s = NULL;
98 st1.s = st2.s = st3.s = NULL;
99 check_o_mode(static_pdf, "immediateobj()", 1 << OMODE_PDF, true);
100 if (global_shipping_mode != NOT_SHIPPING)
101 luaL_error(L, "pdf.immediateobj() can not be used with \\latelua");
102 n = lua_gettop(L);
103 if (n > 0 && lua_type(L, 1) == LUA_TNUMBER) {
104 first_arg++;
105 k=(int)lua_tonumber(L, 1);
106 check_obj_type(static_pdf, obj_type_obj, k);
107 if (is_obj_scheduled(static_pdf, k) || obj_data_ptr(static_pdf, k) != 0)
108 luaL_error(L, "pdf.immediateobj() object in use");
109 } else {
110 static_pdf->obj_count++;
111 k = pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1);
112 }
113 pdf_last_obj = k;
114 switch (n - first_arg + 1) {
115 case 0:
116 luaL_error(L, "pdf.immediateobj() needs at least one argument");
117 break;
118 case 1:
119 if (!lua_isstring(L, first_arg))
120 luaL_error(L, "pdf.immediateobj() 1st argument must be string");
121 pdf_begin_obj(static_pdf, k, OBJSTM_ALWAYS);
122 st1.s = lua_tolstring(L, first_arg, &st1.l);
123 pdf_out_block(static_pdf, st1.s, st1.l);
124 /* already in pdf_end_obj:
125 if (st1.s[st1.l - 1] != '\n')
126 pdf_out(static_pdf, '\n');
127 */
128 pdf_end_obj(static_pdf);
129 break;
130 case 2:
131 case 3:
132 if (!lua_isstring(L, first_arg))
133 luaL_error(L, "pdf.immediateobj() 1st argument must be string");
134 if (!lua_isstring(L, first_arg + 1))
135 luaL_error(L, "pdf.immediateobj() 2nd argument must be string");
136 st1_s = lua_tostring(L, first_arg);
137 st2.s = lua_tolstring(L, first_arg + 1, &st2.l);
138 if (lua_key_eq(st1_s, file)) {
139 if (n == first_arg + 2)
140 luaL_error(L, "pdf.immediateobj() 3rd argument forbidden in file mode");
141 pdf_begin_obj(static_pdf, k, OBJSTM_ALWAYS);
142 buf.s = fread_to_buf(L, st2.s, &buf.l);
143 pdf_out_block(static_pdf, (const char *) buf.s, buf.l);
144 /* already in pdf_end_obj:
145 if (buf.s[buf.l - 1] != '\n')
146 pdf_out(static_pdf, '\n');
147 */
148 xfree(buf.s);
149 pdf_end_obj(static_pdf);
150 } else {
151 pdf_begin_obj(static_pdf, k, OBJSTM_NEVER); /* not an object stream candidate! */
152 pdf_begin_dict(static_pdf);
153 if (n == first_arg + 2) { /* write attr text */
154 if (!lua_isstring(L, first_arg + 2))
155 luaL_error(L, "pdf.immediateobj() 3rd argument must be string");
156 st3.s = lua_tolstring(L, first_arg + 2, &st3.l);
157 pdf_out_block(static_pdf, st3.s, st3.l);
158 if (st3.s[st3.l - 1] != '\n')
159 pdf_out(static_pdf, '\n');
160 }
161 pdf_dict_add_streaminfo(static_pdf);
162 pdf_end_dict(static_pdf);
163 pdf_begin_stream(static_pdf);
164 if (lua_key_eq(st1_s, stream)) {
165 pdf_out_block(static_pdf, st2.s, st2.l);
166 } else if (lua_key_eq(st1_s, streamfile)) {
167 buf.s = fread_to_buf(L, st2.s, &buf.l);
168 pdf_out_block(static_pdf, (const char *) buf.s, buf.l);
169 xfree(buf.s);
170 } else
171 luaL_error(L, "pdf.immediateobj() invalid argument");
172 pdf_end_stream(static_pdf);
173 pdf_end_obj(static_pdf);
174 }
175 break;
176 default:
177 luaL_error(L, "pdf.immediateobj() allows max. 3 arguments");
178 }
179 lua_pushinteger(L, k);
180 return 1;
181 }
182
table_obj(lua_State * L)183 static int table_obj(lua_State * L)
184 {
185 const char *type;
186 int k, obj_compression;
187 int compress_level = -1; /* unset */
188 int os_threshold = OBJSTM_ALWAYS; /* default: put non-stream objects into object streams */
189 int saved_compress_level = static_pdf->compress_level;
190 const_lstring attr, st;
191 lstring buf;
192 int immediate = 0; /* default: not immediate */
193 attr.s = st.s = NULL;
194 attr.l = 0;
195 assert(lua_istable(L, 1)); /* t */
196
197 /* get object "type" */
198
199 lua_key_rawgeti(type);
200 if (lua_isnil(L, -1)) /* !vs t */
201 luaL_error(L, "pdf.obj(): object \"type\" missing");
202 if (!lua_isstring(L, -1)) /* !vs t */
203 luaL_error(L, "pdf.obj(): object \"type\" must be string");
204 type = lua_tostring(L, -1);
205
206 if (! (lua_key_eq(type, raw) || lua_key_eq(type, stream))) {
207 luaL_error(L, "pdf.obj(): \"%s\" is not a valid object type", type); /* i vs t */
208 }
209 lua_pop(L, 1); /* t */
210
211 /* get optional "immediate" */
212
213 lua_key_rawgeti(immediate);
214 if (!lua_isnil(L, -1)) { /* b? t */
215 if (!lua_isboolean(L, -1)) /* !b t */
216 luaL_error(L, "pdf.obj(): \"immediate\" must be boolean");
217 immediate = lua_toboolean(L, -1); /* 0 or 1 */
218 }
219 lua_pop(L, 1); /* t */
220
221 /* is a reserved object referenced by "objnum"? */
222
223 lua_key_rawgeti(objnum);
224 if (!lua_isnil(L, -1)) { /* vi? t */
225 if (!lua_isnumber(L, -1)) /* !vi t */
226 luaL_error(L, "pdf.obj(): \"objnum\" must be integer");
227 k = (int) lua_tointeger(L, -1); /* vi t */
228 check_obj_type(static_pdf, obj_type_obj, k);
229 if (is_obj_scheduled(static_pdf, k) || obj_data_ptr(static_pdf, k) != 0)
230 luaL_error(L, "pdf.obj() object in use");
231 } else {
232 static_pdf->obj_count++;
233 k = pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1);
234 }
235 pdf_last_obj = k;
236 if (immediate == 0) {
237 obj_data_ptr(static_pdf, k) = pdf_get_mem(static_pdf, pdfmem_obj_size);
238 init_obj_obj(static_pdf, k);
239 }
240 lua_pop(L, 1); /* t */
241
242 /* get optional "attr" (allowed only for stream case) */
243
244 lua_key_rawgeti(attr);
245 if (!lua_isnil(L, -1)) { /* attr-s? t */
246 if (! lua_key_eq(type, stream))
247 luaL_error(L, "pdf.obj(): \"attr\" key not allowed for non-stream object");
248 if (!lua_isstring(L, -1)) /* !attr-s t */
249 luaL_error(L, "pdf.obj(): object \"attr\" must be string");
250 if (immediate == 1) {
251 attr.s = lua_tolstring(L, -1, &attr.l); /* attr-s t */
252 lua_pop(L, 1); /* t */
253 } else
254 obj_obj_stream_attr(static_pdf, k) = luaL_ref(Luas, LUA_REGISTRYINDEX); /* t */
255 } else {
256 lua_pop(L, 1); /* t */
257 }
258
259 /* get optional "compresslevel" (allowed only for stream case) */
260
261 lua_key_rawgeti(compresslevel);
262 if (!lua_isnil(L, -1)) { /* vi? t */
263 if (lua_key_eq(type, raw))
264 luaL_error(L, "pdf.obj(): \"compresslevel\" key not allowed for raw object");
265 if (!lua_isnumber(L, -1)) /* !vi t */
266 luaL_error(L, "pdf.obj(): \"compresslevel\" must be integer");
267 compress_level = (int) lua_tointeger(L, -1); /* vi t */
268 if (compress_level > 9)
269 luaL_error(L, "pdf.obj(): \"compresslevel\" must be <= 9");
270 else if (compress_level < 0)
271 luaL_error(L, "pdf.obj(): \"compresslevel\" must be >= 0");
272 if (immediate == 0)
273 obj_obj_pdfcompresslevel(static_pdf, k) = compress_level;
274 }
275 lua_pop(L, 1); /* t */
276
277 /* get optional "objcompression" (allowed only for non-stream case) */
278
279 lua_key_rawgeti(objcompression);
280 if (!lua_isnil(L, -1)) { /* b? t */
281 if (lua_key_eq(type, stream))
282 luaL_error(L, "pdf.obj(): \"objcompression\" key not allowed for stream object");
283 if (!lua_isboolean(L, -1)) /* !b t */
284 luaL_error(L, "pdf.obj(): \"objcompression\" must be boolean");
285 obj_compression = lua_toboolean(L, -1); /* 0 or 1 */
286 /* OBJSTM_NEVER: never into object stream; OBJSTM_ALWAYS: depends then on \pdfobjcompresslevel */
287 if (obj_compression > 0)
288 os_threshold = OBJSTM_ALWAYS;
289 else
290 os_threshold = OBJSTM_NEVER;
291 if (immediate == 0)
292 obj_obj_objstm_threshold(static_pdf, k) = os_threshold;
293 }
294 lua_pop(L, 1); /* t */
295
296 /* now the object contents for all cases are handled */
297
298 lua_key_rawgeti(string);
299 lua_key_rawgeti_n(file,-2);
300
301 if (!lua_isnil(L, -1) && !lua_isnil(L, -2)) /* file-s? string-s? t */
302 luaL_error(L, "pdf.obj(): \"string\" and \"file\" must not be given together");
303 if (lua_isnil(L, -1) && lua_isnil(L, -2)) /* nil nil t */
304 luaL_error(L, "pdf.obj(): no \"string\" or \"file\" given");
305
306 if (lua_key_eq(type, raw)) {
307 if (immediate == 1)
308 pdf_begin_obj(static_pdf, k, os_threshold);
309 if (!lua_isnil(L, -2)) { /* file-s? string-s? t */
310 /* from string */
311 lua_pop(L, 1); /* string-s? t */
312 if (!lua_isstring(L, -1)) /* !string-s t */
313 luaL_error(L, "pdf.obj(): \"string\" must be string for raw object");
314 if (immediate == 1) {
315 st.s = lua_tolstring(L, -1, &st.l);
316 pdf_out_block(static_pdf, st.s, st.l);
317 /* already in pdf_end_obj:
318 if (st.s[st.l - 1] != '\n')
319 pdf_out(static_pdf, '\n');
320 */
321 } else
322 obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* t */
323 } else {
324 /* from file */
325 if (!lua_isstring(L, -1)) /* !file-s nil t */
326 luaL_error(L, "pdf.obj(): \"file\" name must be string for raw object");
327 if (immediate == 1) {
328 st.s = lua_tolstring(L, -1, &st.l); /* file-s nil t */
329 buf.s = fread_to_buf(L, st.s, &buf.l);
330 pdf_out_block(static_pdf, (const char *) buf.s, buf.l);
331 /* already in pdf_end_obj:
332 if (buf.s[buf.l - 1] != '\n')
333 pdf_out(static_pdf, '\n');
334 */
335 xfree(buf.s);
336 } else {
337 set_obj_obj_is_file(static_pdf, k);
338 obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* nil t */
339 }
340 }
341 if (immediate == 1)
342 pdf_end_obj(static_pdf);
343 } else {
344 if (immediate == 1) {
345 pdf_begin_obj(static_pdf, k, OBJSTM_NEVER); /* 0 = not an object stream candidate! */
346 pdf_begin_dict(static_pdf);
347 if (attr.s != NULL) {
348 pdf_out_block(static_pdf, attr.s, attr.l);
349 if (attr.s[attr.l - 1] != '\n')
350 pdf_out(static_pdf, '\n');
351 }
352 if (compress_level > -1)
353 static_pdf->compress_level = compress_level;
354 pdf_dict_add_streaminfo(static_pdf);
355 pdf_end_dict(static_pdf);
356 pdf_begin_stream(static_pdf);
357 } else {
358 set_obj_obj_is_stream(static_pdf, k);
359 if (compress_level > -1)
360 obj_obj_pdfcompresslevel(static_pdf, k) = compress_level;
361 }
362 if (!lua_isnil(L, -2)) { /* file-s? string-s? t */
363 /* from string */
364 lua_pop(L, 1); /* string-s? t */
365 if (!lua_isstring(L, -1)) /* !string-s t */
366 luaL_error(L, "pdf.obj(): \"string\" must be string for stream object");
367 if (immediate == 1) {
368 st.s = lua_tolstring(L, -1, &st.l); /* string-s t */
369 pdf_out_block(static_pdf, st.s, st.l);
370 } else
371 obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* t */
372 } else {
373 /* from file */
374 if (!lua_isstring(L, -1)) /* !file-s nil t */
375 luaL_error(L, "pdf.obj(): \"file\" name must be string for stream object");
376 if (immediate == 1) {
377 st.s = lua_tolstring(L, -1, &st.l); /* file-s nil t */
378 buf.s = fread_to_buf(L, st.s, &buf.l);
379 pdf_out_block(static_pdf, (const char *) buf.s, buf.l);
380 xfree(buf.s);
381 } else {
382 set_obj_obj_is_file(static_pdf, k);
383 obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* nil t */
384 }
385 }
386 if (immediate == 1) {
387 pdf_end_stream(static_pdf);
388 pdf_end_obj(static_pdf);
389 }
390 }
391 static_pdf->compress_level = saved_compress_level;
392 return k;
393 }
394
orig_obj(lua_State * L)395 static int orig_obj(lua_State * L)
396 {
397 int n, first_arg = 1;
398 int k;
399 const char *st_s = NULL ;
400 n = lua_gettop(L);
401 if (n > 0 && lua_type(L, 1) == LUA_TNUMBER) {
402 first_arg++;
403 k=(int)lua_tonumber(L, 1);
404 check_obj_type(static_pdf, obj_type_obj, k);
405 if (is_obj_scheduled(static_pdf, k) || obj_data_ptr(static_pdf, k) != 0)
406 luaL_error(L, "pdf.obj() object in use");
407 } else {
408 static_pdf->obj_count++;
409 k = pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1);
410 }
411 pdf_last_obj = k;
412 obj_data_ptr(static_pdf, k) = pdf_get_mem(static_pdf, pdfmem_obj_size);
413 init_obj_obj(static_pdf, k);
414 switch (n - first_arg + 1) {
415 case 0:
416 luaL_error(L, "pdf.obj() needs at least one argument");
417 break;
418 case 1:
419 if (!lua_isstring(L, first_arg))
420 luaL_error(L, "pdf.obj() 1st argument must be string");
421 break;
422 case 2:
423 case 3:
424 if (!lua_isstring(L, first_arg))
425 luaL_error(L, "pdf.obj() 1st argument must be string");
426 if (!lua_isstring(L, first_arg + 1))
427 luaL_error(L, "pdf.obj() 2nd argument must be string");
428 st_s = lua_tostring(L, first_arg);
429 if (lua_key_eq(st_s, file)) {
430 if (n == first_arg + 2)
431 luaL_error(L, "pdf.obj() 3rd argument forbidden in file mode");
432 set_obj_obj_is_file(static_pdf, k);
433 } else {
434 if (n == first_arg + 2) { /* write attr text */
435 if (!lua_isstring(L, -1))
436 luaL_error(L, "pdf.obj() 3rd argument must be string");
437 obj_obj_stream_attr(static_pdf, k) =
438 luaL_ref(Luas, LUA_REGISTRYINDEX);
439 }
440 if (lua_key_eq(st_s, stream)) {
441 set_obj_obj_is_stream(static_pdf, k);
442 } else if (lua_key_eq(st_s, streamfile)) {
443 set_obj_obj_is_stream(static_pdf, k);
444 set_obj_obj_is_file(static_pdf, k);
445 } else
446 luaL_error(L, "pdf.obj() invalid argument");
447 }
448 break;
449 default:
450 luaL_error(L, "pdf.obj() allows max. 3 arguments");
451 }
452 obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX);
453 return k;
454 }
455
l_obj(lua_State * L)456 static int l_obj(lua_State * L)
457 {
458 int k, n;
459 ensure_output_state(static_pdf, ST_HEADER_WRITTEN);
460 n = lua_gettop(L);
461 if (n == 1 && lua_istable(L, 1))
462 k = table_obj(L); /* new */
463 else
464 k = orig_obj(L);
465 lua_pushinteger(L, k);
466 return 1;
467 }
468
l_refobj(lua_State * L)469 static int l_refobj(lua_State * L)
470 {
471 int k, n;
472 n = lua_gettop(L);
473 if (n != 1)
474 luaL_error(L, "pdf.refobj() needs exactly 1 argument");
475 k = (int) luaL_checkinteger(L, 1);
476 if (global_shipping_mode == NOT_SHIPPING)
477 scan_refobj_lua(static_pdf, k);
478 else
479 pdf_ref_obj_lua(static_pdf, k);
480 return 0;
481 }
482
l_reserveobj(lua_State * L)483 static int l_reserveobj(lua_State * L)
484 {
485 int n;
486 const char *st_s = NULL;
487 n = lua_gettop(L);
488 switch (n) {
489 case 0:
490 static_pdf->obj_count++;
491 pdf_last_obj =
492 pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1);
493 break;
494 case 1:
495 if (!lua_isstring(L, -1))
496 luaL_error(L, "pdf.reserveobj() optional argument must be string");
497 if (lua_key_eq(st_s, annot)) {
498 pdf_last_annot = pdf_create_obj(static_pdf, obj_type_annot, 0);
499 } else {
500 luaL_error(L, "pdf.reserveobj() optional string must be \"annot\"");
501 }
502 lua_pop(L, 1);
503 break;
504 default:
505 luaL_error(L, "pdf.reserveobj() allows max. 1 argument");
506 }
507 lua_pushinteger(L, static_pdf->obj_ptr);
508 return 1;
509 }
510
l_registerannot(lua_State * L)511 static int l_registerannot(lua_State * L)
512 {
513 int n, i;
514 n = lua_gettop(L);
515 switch (n) {
516 case 1:
517 if (global_shipping_mode == NOT_SHIPPING)
518 luaL_error(L, "pdf.registerannot() can only be used in late lua");
519 i = (int) luaL_checkinteger(L, 1);
520 if (i <= 0)
521 luaL_error(L, "pdf.registerannot() can only register positive object numbers");
522 addto_page_resources(static_pdf, obj_type_annot, i);
523 break;
524 default:
525 luaL_error(L, "pdf.registerannot() needs exactly 1 argument");
526 }
527 return 0;
528 }
529
l_get_pdf_value(lua_State * L,int key)530 static int l_get_pdf_value(lua_State * L, int key)
531 {
532 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(pdf_data));
533 lua_gettable(L, LUA_REGISTRYINDEX);
534 /* [table] */
535 lua_rawgeti(L, LUA_REGISTRYINDEX, key);
536 /* [table] [key] */
537 lua_rawget(L,-2);
538 return 1;
539 }
l_get_pageresources(lua_State * L)540 static int l_get_pageresources(lua_State * L) {
541 return l_get_pdf_value(L,lua_key_index(pageresources));
542 }
l_get_pageattributes(lua_State * L)543 static int l_get_pageattributes(lua_State * L) {
544 return l_get_pdf_value(L,lua_key_index(pageattributes));
545 }
l_get_pagesattributes(lua_State * L)546 static int l_get_pagesattributes(lua_State * L) {
547 return l_get_pdf_value(L,lua_key_index(pagesattributes));
548 }
l_get_catalog(lua_State * L)549 static int l_get_catalog(lua_State * L) {
550 return l_get_pdf_value(L,lua_key_index(catalog));
551 }
l_get_info(lua_State * L)552 static int l_get_info(lua_State * L) {
553 return l_get_pdf_value(L,lua_key_index(info));
554 }
l_get_names(lua_State * L)555 static int l_get_names(lua_State * L) {
556 return l_get_pdf_value(L,lua_key_index(names));
557 }
558
559
l_get_trailer(lua_State * L)560 static int l_get_trailer(lua_State * L) {
561 return l_get_pdf_value(L,lua_key_index(trailer));
562 }
563
564
getpdf(lua_State * L)565 static int getpdf(lua_State * L)
566 {
567 /* [pdf table] [key] */
568 const char *s ;
569 if (lua_gettop(L) != 2) {
570 return 0;
571 }
572 if (lua_isstring(L, -1)) {
573 s = lua_tostring(L, -1);
574 if (lua_key_eq(s,h)) {
575 lua_pushnumber(L, static_pdf->posstruct->pos.h);
576 return 1;
577 } else if (lua_key_eq(s,v)) {
578 lua_pushnumber(L, static_pdf->posstruct->pos.v);
579 return 1;
580 } else if (
581 lua_key_eq(s,catalog) || lua_key_eq(s,info) || lua_key_eq(s,trailer) || lua_key_eq(s,names) ||
582 lua_key_eq(s,pageattributes) || lua_key_eq(s,pagesattributes) || lua_key_eq(s,pageresources)
583 ) {
584 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(pdf_data));
585 lua_gettable(L, LUA_REGISTRYINDEX);
586 /* [pdf table] [key] [pdf.data table] */
587 lua_replace(L, -3);
588 /* [pdf.data table] [key] */
589 lua_rawget(L, -2);
590 return 1;
591 }
592 }
593 return 0;
594 }
595
596
597
598
l_set_pdf_value(lua_State * L,int key)599 static int l_set_pdf_value(lua_State * L, int key)
600 {
601 if (lua_isstring(L, -1)) {
602 /* [value] */
603 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(pdf_data));
604 lua_gettable(L, LUA_REGISTRYINDEX);
605 /* [value] [table] */
606 lua_rawgeti(L, LUA_REGISTRYINDEX, key);
607 /* [value] [table] [key] */
608 lua_pushvalue(L, -3);
609 /* [table] [key] [value] */
610 lua_rawset(L,-3);
611 }
612 return 0;
613 }
l_set_pageresources(lua_State * L)614 static int l_set_pageresources(lua_State * L) {
615 return l_set_pdf_value(L,lua_key_index(pageresources));
616 }
l_set_pageattributes(lua_State * L)617 static int l_set_pageattributes(lua_State * L) {
618 return l_set_pdf_value(L,lua_key_index(pageattributes));
619 }
l_set_pagesattributes(lua_State * L)620 static int l_set_pagesattributes(lua_State * L) {
621 return l_set_pdf_value(L,lua_key_index(pagesattributes));
622 }
l_set_catalog(lua_State * L)623 static int l_set_catalog(lua_State * L) {
624 return l_set_pdf_value(L,lua_key_index(catalog));
625 }
l_set_info(lua_State * L)626 static int l_set_info(lua_State * L) {
627 return l_set_pdf_value(L,lua_key_index(info));
628 }
l_set_names(lua_State * L)629 static int l_set_names(lua_State * L) {
630 return l_set_pdf_value(L,lua_key_index(names));
631 }
l_set_trailer(lua_State * L)632 static int l_set_trailer(lua_State * L) {
633 return l_set_pdf_value(L,lua_key_index(trailer));
634 }
635
636
setpdf(lua_State * L)637 static int setpdf(lua_State * L)
638 {
639 /* [pdf table] [key] [value] */
640 const char *s ;
641 if (lua_gettop(L) != 3) {
642 return 0;
643 }
644 if (lua_isstring(L, -2)) {
645 s = lua_tostring(L, -1);
646 if (
647 lua_key_eq(s,catalog) || lua_key_eq(s,info) || lua_key_eq(s,trailer) || lua_key_eq(s,names) ||
648 lua_key_eq(s,pageattributes) || lua_key_eq(s,pagesattributes) || lua_key_eq(s,pageresources)
649 ) {
650 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(pdf_data));
651 lua_gettable(L, LUA_REGISTRYINDEX);
652 /* [pdf table] [key] [value] [pdf.data table] */
653 lua_replace(L, -4);
654 /* [pdf.data table] [key] [value] */
655 }
656 }
657 lua_rawset(L, -3);
658 return 0;
659 }
660
661
l_objtype(lua_State * L)662 static int l_objtype(lua_State * L)
663 {
664 int n = lua_gettop(L);
665 if (n != 1)
666 luaL_error(L, "pdf.objtype() needs exactly 1 argument");
667 n = (int) luaL_checkinteger(L, 1);
668 if (n < 0 || n > static_pdf->obj_ptr)
669 lua_pushnil(L);
670 else
671 lua_pushstring(L, pdf_obj_typenames[obj_type(static_pdf, n)]);
672 return 1;
673 }
674
l_maxobjnum(lua_State * L)675 static int l_maxobjnum(lua_State * L)
676 {
677 int n = lua_gettop(L);
678 if (n != 0)
679 luaL_error(L, "pdf.maxobjnum() needs 0 arguments");
680 lua_pushinteger(L, static_pdf->obj_ptr);
681 return 1;
682 }
683
l_mapfile(lua_State * L)684 static int l_mapfile(lua_State * L)
685 {
686 char *s;
687 const char *st;
688 if (lua_isstring(L, -1) && (st = lua_tostring(L, -1)) != NULL) {
689 s = xstrdup(st);
690 process_map_item(s, MAPFILE);
691 free(s);
692 }
693 return 0;
694 }
695
l_mapline(lua_State * L)696 static int l_mapline(lua_State * L)
697 {
698 char *s;
699 const char *st;
700 if (lua_isstring(L, -1) && (st = lua_tostring(L, -1)) != NULL) {
701 s = xstrdup(st);
702 process_map_item(s, MAPLINE);
703 free(s);
704 }
705 return 0;
706 }
707
l_pageref(lua_State * L)708 static int l_pageref(lua_State * L)
709 {
710 int n = lua_gettop(L);
711 if (n != 1)
712 luaL_error(L, "pdf.pageref() needs exactly 1 argument");
713 n = (int) luaL_checkinteger(L, 1);
714 if (n <= 0)
715 luaL_error(L, "pdf.pageref() needs page number > 0");
716 n = pdf_get_obj(static_pdf, obj_type_page, n, false);
717 lua_pushnumber(L, n);
718 return 1;
719 }
720
l_getpos(lua_State * L)721 static int l_getpos(lua_State * L)
722 {
723 lua_pushnumber(L, static_pdf->posstruct->pos.h);
724 lua_pushnumber(L, static_pdf->posstruct->pos.v);
725 return 2;
726 }
727
l_gethpos(lua_State * L)728 static int l_gethpos(lua_State * L)
729 {
730 lua_pushnumber(L, static_pdf->posstruct->pos.h);
731 return 1;
732 }
733
l_getvpos(lua_State * L)734 static int l_getvpos(lua_State * L)
735 {
736 lua_pushnumber(L, static_pdf->posstruct->pos.v);
737 return 1;
738 }
739
l_getmatrix(lua_State * L)740 static int l_getmatrix(lua_State * L)
741 {
742 if (matrix_stack_used > 0) {
743 matrix_entry *m = &matrix_stack[matrix_stack_used - 1];
744 lua_pushnumber(L, m->a);
745 lua_pushnumber(L, m->b);
746 lua_pushnumber(L, m->c);
747 lua_pushnumber(L, m->d);
748 lua_pushnumber(L, m->e);
749 lua_pushnumber(L, m->f);
750 } else {
751 lua_pushnumber(L, 1);
752 lua_pushnumber(L, 0);
753 lua_pushnumber(L, 0);
754 lua_pushnumber(L, 1);
755 lua_pushnumber(L, 0);
756 lua_pushnumber(L, 0);
757 }
758 return 6 ;
759 }
760
l_hasmatrix(lua_State * L)761 static int l_hasmatrix(lua_State * L)
762 {
763 lua_pushboolean(L, (matrix_stack_used > 0));
764 return 1 ;
765 }
766
767
768 static const struct luaL_Reg pdflib[] = {
769 {"immediateobj", l_immediateobj},
770 {"mapfile", l_mapfile},
771 {"mapline", l_mapline},
772 {"maxobjnum", l_maxobjnum},
773 {"obj", l_obj},
774 {"objtype", l_objtype},
775 {"pageref", l_pageref},
776 {"print", luapdfprint},
777 {"refobj", l_refobj},
778 {"registerannot", l_registerannot},
779 {"reserveobj", l_reserveobj},
780 {"getpos", l_getpos},
781 {"gethpos", l_gethpos},
782 {"getvpos", l_getvpos},
783 {"getmatrix", l_getmatrix},
784 {"hasmatrix", l_hasmatrix},
785 {"setcatalog", l_set_catalog},
786 {"setinfo", l_set_info},
787 {"setnames", l_set_names},
788 {"settrailer", l_set_trailer},
789 {"setpageresources", l_set_pageresources},
790 {"setpageattributes", l_set_pageattributes},
791 {"setpagesattributes", l_set_pagesattributes},
792 {"getcatalog", l_get_catalog},
793 {"getinfo", l_get_info},
794 {"getnames", l_get_names},
795 {"gettrailer", l_get_trailer},
796 {"getpageresources", l_get_pageresources},
797 {"getpageattributes", l_get_pageattributes},
798 {"getpagesattributes", l_get_pagesattributes},
799 {NULL, NULL} /* sentinel */
800 };
801
802 /**********************************************************************/
803
luaopen_pdf(lua_State * L)804 int luaopen_pdf(lua_State * L)
805 {
806 lua_pushstring(L,"pdf.data");
807 lua_newtable(L);
808 lua_settable(L,LUA_REGISTRYINDEX);
809 /* */
810 luaL_register(L, "pdf", pdflib);
811 /* build meta table */
812 luaL_newmetatable(L, "pdf.meta");
813 lua_pushstring(L, "__index");
814 lua_pushcfunction(L, getpdf);
815 /* do these later, NYI */
816 lua_settable(L, -3);
817 lua_pushstring(L, "__newindex");
818 lua_pushcfunction(L, setpdf);
819 lua_settable(L, -3);
820 lua_setmetatable(L, -2); /* meta to itself */
821 return 1;
822 }
823