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