1% pdfobj.w
2%
3% Copyright 2009-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@ @c
21
22
23#include "ptexlib.h"
24#include "lua/luatex-api.h"
25
26int pdf_last_obj;
27
28@ write a raw PDF object
29
30@c
31void pdf_write_obj(PDF pdf, int k)
32{
33    lstring data;
34    const_lstring st;
35    size_t li;                  /* index into |data.s| */
36    int saved_compress_level = pdf->compress_level;
37    int os_threshold = OBJSTM_ALWAYS;   /* gives compressed objects for \.{\\pdfobjcompresslevel} >= |OBJSTM_ALWAYS| */
38    int l = 0;                  /* possibly a lua registry reference */
39    int ll = 0;
40    data.s = NULL;
41    if (obj_obj_pdfcompresslevel(pdf, k) > -1)  /* -1 = "unset" */
42        pdf->compress_level = obj_obj_pdfcompresslevel(pdf, k);
43    if (obj_obj_objstm_threshold(pdf, k) != OBJSTM_UNSET)
44        os_threshold = obj_obj_objstm_threshold(pdf, k);
45    if (obj_obj_is_stream(pdf, k)) {
46        pdf_begin_obj(pdf, k, OBJSTM_NEVER);
47        pdf_begin_dict(pdf);
48        l = obj_obj_stream_attr(pdf, k);
49        if (l != LUA_NOREF) {
50            lua_rawgeti(Luas, LUA_REGISTRYINDEX, l);
51            assert(lua_isstring(Luas, -1));
52            st.s = lua_tolstring(Luas, -1, &li);
53            st.l = li;
54            pdf_out_block(pdf, st.s, st.l);
55            if (st.s[st.l - 1] != '\n')
56                pdf_out(pdf, '\n');
57            luaL_unref(Luas, LUA_REGISTRYINDEX, l);
58            obj_obj_stream_attr(pdf, k) = LUA_NOREF;
59        }
60        pdf_dict_add_streaminfo(pdf);
61        pdf_end_dict(pdf);
62        pdf_begin_stream(pdf);
63    } else
64        pdf_begin_obj(pdf, k, os_threshold);
65    l = obj_obj_data(pdf, k);
66    lua_rawgeti(Luas, LUA_REGISTRYINDEX, l);
67    assert(lua_isstring(Luas, -1));
68    st.s = lua_tolstring(Luas, -1, &li);
69    st.l = li;
70    lua_pop(Luas, 1);
71    if (obj_obj_is_file(pdf, k)) {
72        boolean res = false;    /* callback status value */
73        const char *fnam = NULL;        /* callback found filename */
74        int callback_id;
75        /* st.s is also |\0|-terminated, even as lstring */
76        fnam = luatex_find_file(st.s, find_data_file_callback);
77        callback_id = callback_defined(read_data_file_callback);
78        if (fnam && callback_id > 0) {
79            boolean file_opened = false;
80            res = run_callback(callback_id, "S->bSd", fnam, &file_opened, &data.s, &ll);
81            data.l = (size_t) ll;
82            if (!file_opened)
83                pdf_error("ext5", "cannot open file for embedding");
84        } else {
85            byte_file f;        /* the data file's FILE* */
86            if (!fnam)
87                fnam = st.s;
88            if (!luatex_open_input(&f, fnam, kpse_tex_format, FOPEN_RBIN_MODE, true))
89                pdf_error("ext5", "cannot open file for embedding");
90            res = read_data_file(f, &data.s, &ll);
91            data.l = (size_t) ll;
92            close_file(f);
93        }
94        if (data.l == 0L)
95            pdf_error("ext5", "empty file for embedding");
96        if (!res)
97            pdf_error("ext5", "error reading file for embedding");
98        tprint("<<");
99        tprint(st.s);
100        pdf_out_block(pdf, (const char *) data.s, data.l);
101        /* already happens in pdf_end_obj:
102            if (!obj_obj_is_stream(pdf, k) && data.s[data.l - 1] != '\n')
103                pdf_out(pdf, '\n');
104        */
105        xfree(data.s);
106        tprint(">>");
107    } else {
108        pdf_out_block(pdf, st.s, st.l);
109        /* already happens in pdf_end_obj:
110            if (!obj_obj_is_stream(pdf, k) && st.s[st.l - 1] != '\n')
111                pdf_out(pdf, '\n');
112        */
113    }
114    if (obj_obj_is_stream(pdf, k)) {
115        pdf_end_stream(pdf);
116        pdf_end_obj(pdf);
117    } else /* here we do the \n */
118        pdf_end_obj(pdf);
119    luaL_unref(Luas, LUA_REGISTRYINDEX, l);
120    obj_obj_data(pdf, k) = LUA_NOREF;
121    pdf->compress_level = saved_compress_level;
122}
123
124@ @c
125void init_obj_obj(PDF pdf, int k)
126{
127    obj_obj_stream_attr(pdf, k) = LUA_NOREF;
128    obj_obj_data(pdf, k) = LUA_NOREF;
129    unset_obj_obj_is_stream(pdf, k);
130    unset_obj_obj_is_file(pdf, k);
131    obj_obj_pdfcompresslevel(pdf, k) = -1;      /* unset */
132    obj_obj_objstm_threshold(pdf, k) = OBJSTM_UNSET;  /* unset */
133}
134
135@ The \.{\\pdfobj} primitive is used to create a ``raw'' object in the PDF
136   output file. The object contents will be hold in memory and will be written
137   out only when the object is referenced by \.{\\pdfrefobj}. When \.{\\pdfobj}
138   is used with \.{\\immediate}, the object contents will be written out
139   immediately. Objects referenced in the current page are appended into
140   |pdf_obj_list|.
141
142@c
143void scan_obj(PDF pdf)
144{
145    int k;
146    lstring *st = NULL;
147    if (scan_keyword("reserveobjnum")) {
148        /* Scan an optional space */
149        get_x_token();
150        if (cur_cmd != spacer_cmd)
151            back_input();
152        pdf->obj_count++;
153        k = pdf_create_obj(pdf, obj_type_obj, 0);
154    } else {
155        if (scan_keyword("useobjnum")) {
156            scan_int();
157            k = cur_val;
158            check_obj_type(pdf, obj_type_obj, k);
159            if (is_obj_scheduled(pdf, k) || obj_data_ptr(pdf, k) != 0)
160                luaL_error(Luas, "object in use");
161        } else {
162            pdf->obj_count++;
163            k = pdf_create_obj(pdf, obj_type_obj, 0);
164        }
165        obj_data_ptr(pdf, k) = pdf_get_mem(pdf, pdfmem_obj_size);
166        init_obj_obj(pdf, k);
167        if (scan_keyword("uncompressed")) {
168            obj_obj_pdfcompresslevel(pdf, k) = 0;       /* \pdfcompresslevel = 0 */
169            obj_obj_objstm_threshold(pdf, k) = OBJSTM_NEVER;
170        }
171        if (scan_keyword("stream")) {
172            set_obj_obj_is_stream(pdf, k);
173            if (scan_keyword("attr")) {
174                scan_pdf_ext_toks();
175                st = tokenlist_to_lstring(def_ref, true);
176                flush_list(def_ref);
177                lua_pushlstring(Luas, (char *) st->s, st->l);
178                obj_obj_stream_attr(pdf, k) = luaL_ref(Luas, LUA_REGISTRYINDEX);
179                free_lstring(st);
180                st = NULL;
181            }
182        }
183        if (scan_keyword("file"))
184            set_obj_obj_is_file(pdf, k);
185        scan_pdf_ext_toks();
186        st = tokenlist_to_lstring(def_ref, true);
187        flush_list(def_ref);
188        lua_pushlstring(Luas, (char *) st->s, st->l);
189        obj_obj_data(pdf, k) = luaL_ref(Luas, LUA_REGISTRYINDEX);
190        free_lstring(st);
191        st = NULL;
192    }
193    pdf_last_obj = k;
194}
195
196@ @c
197#define tail          cur_list.tail_field
198
199void scan_refobj(PDF pdf)
200{
201    scan_int();
202    check_obj_type(pdf, obj_type_obj, cur_val);
203    new_whatsit(pdf_refobj_node);
204    pdf_obj_objnum(tail) = cur_val;
205}
206
207void scan_refobj_lua(PDF pdf, int k)
208{
209    check_obj_type(pdf, obj_type_obj, k);
210    new_whatsit(pdf_refobj_node);
211    pdf_obj_objnum(tail) = k;
212}
213
214@ @c
215void pdf_ref_obj(PDF pdf, halfword p)
216{
217    if (!is_obj_scheduled(pdf, pdf_obj_objnum(p)))
218        addto_page_resources(pdf, obj_type_obj, pdf_obj_objnum(p));
219}
220
221@ @c
222void pdf_ref_obj_lua(PDF pdf, int k)
223{
224    if (!is_obj_scheduled(pdf, k))
225        addto_page_resources(pdf, obj_type_obj, k);
226}
227