1% pdfshipout.w 2% 3% Copyright 2010-2012 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 25@ @c 26#define count(A) eqtb[count_base+(A)].cint 27#define h_offset dimen_par(h_offset_code) 28#define mag int_par(mag_code) 29#define page_bottom_offset dimen_par(page_bottom_offset_code) 30#define page_direction int_par(page_direction_code) 31#define page_height dimen_par(page_height_code) 32#define page_left_offset dimen_par(page_left_offset_code) 33#define page_right_offset dimen_par(page_right_offset_code) 34#define page_top_offset dimen_par(page_top_offset_code) 35#define page_width dimen_par(page_width_code) 36#define pdf_h_origin dimen_par(pdf_h_origin_code) 37#define pdf_v_origin dimen_par(pdf_v_origin_code) 38#define tracing_output int_par(tracing_output_code) 39#define tracing_stats int_par(tracing_stats_code) 40#define v_offset dimen_par(v_offset_code) 41 42scaledpos shipbox_refpos; 43 44@ |ship_out| is used to shipout a box to PDF or DVI mode. 45If |shipping_mode| is set to |SHIPPING_FORM| then the output will be a Form object 46(only PDF), and if it is set to |SHIPPING_PAGE| it will be a Page object. 47 48@c 49void ship_out(PDF pdf, halfword p, shipping_mode_e shipping_mode) 50{ 51 /* output the box |p| */ 52 int j, k; /* indices to first ten count registers */ 53 int post_callback_id; 54 int pre_callback_id; 55 posstructure refpoint; /* the origin pos. on the page */ 56 scaledpos cur = { 0, 0 }; 57 refpoint.pos.h = 0; 58 refpoint.pos.v = 0; 59 60 ensure_output_state(pdf, ST_HEADER_WRITTEN); 61 fix_o_mode(pdf); /* this is only for complaining if \.{\\pdfoutput} has changed */ 62 init_backend_functionpointers(pdf->o_mode); 63 64 pdf->f_cur = null_font; 65 66 /* Start sheet {\sl Sync\TeX} information record */ 67 /* {\sl Sync\TeX}: we assume that |pdf_output| is properly set up */ 68 if (int_par(synctex_code)) 69 synctexsheet(mag); 70 71 pre_callback_id = callback_defined(start_page_number_callback); 72 post_callback_id = callback_defined(stop_page_number_callback); 73 if ((tracing_output > 0) && (pre_callback_id == 0)) { 74 tprint_nl(""); 75 print_ln(); 76 tprint("Completed box being shipped out"); 77 } 78 global_shipping_mode = shipping_mode; 79 if (shipping_mode == SHIPPING_PAGE) { 80 if (pre_callback_id > 0) 81 (void) run_callback(pre_callback_id, "->"); 82 else if (pre_callback_id == 0) { 83 if (term_offset > max_print_line - 9) 84 print_ln(); 85 else if ((term_offset > 0) || (file_offset > 0)) 86 print_char(' '); 87 print_char('['); 88 j = 9; 89 while ((count(j) == 0) && (j > 0)) 90 j--; 91 for (k = 0; k <= j; k++) { 92 print_int(count(k)); 93 if (k < j) 94 print_char('.'); 95 } 96 } 97 } 98 if ((tracing_output > 0) && shipping_mode == SHIPPING_PAGE) { 99 print_char(']'); 100 update_terminal(); 101 begin_diagnostic(); 102 show_box(p); 103 end_diagnostic(true); 104 } 105 106 /* Ship box |p| out */ 107 if (shipping_mode == SHIPPING_PAGE && box_dir(p) != page_direction) 108 pdf_warning("\\shipout", 109 "\\pagedir != \\bodydir; " 110 "\\box\\outputbox may be placed wrongly on the page.", true, 111 true); 112 /* Update the values of |max_h| and |max_v|; but if the page is too large, |goto done| */ 113 /* Sometimes the user will generate a huge page because other error messages 114 are being ignored. Such pages are not output to the \.{dvi} file, since they 115 may confuse the printing software. */ 116 117 if ((height(p) > max_dimen) || (depth(p) > max_dimen) 118 || (height(p) + depth(p) + v_offset > max_dimen) 119 || (width(p) + h_offset > max_dimen)) { 120 const char *hlp[] = 121 { "The page just created is more than 18 feet tall or", 122 "more than 18 feet wide, so I suspect something went wrong.", 123 NULL 124 }; 125 tex_error("Huge page cannot be shipped out", hlp); 126 if (tracing_output <= 0) { 127 begin_diagnostic(); 128 tprint_nl("The following box has been deleted:"); 129 show_box(p); 130 end_diagnostic(true); 131 } 132 goto DONE; 133 } 134 if (height(p) + depth(p) + v_offset > max_v) 135 max_v = height(p) + depth(p) + v_offset; 136 if (width(p) + h_offset > max_h) 137 max_h = width(p) + h_offset; 138 139 /* Calculate page dimensions and margins */ 140 if (global_shipping_mode == SHIPPING_PAGE) { 141 if (page_width > 0) 142 pdf->page_size.h = page_width; 143 else { 144 switch (page_direction) { 145 case dir_TLT: 146 pdf->page_size.h = width(p) + 2 * page_left_offset; 147 break; 148 case dir_TRT: 149 pdf->page_size.h = width(p) + 2 * page_right_offset; 150 break; 151 case dir_LTL: 152 pdf->page_size.h = height(p) + depth(p) + 2 * page_left_offset; 153 break; 154 case dir_RTT: 155 pdf->page_size.h = height(p) + depth(p) + 2 * page_right_offset; 156 break; 157 default: 158 assert(0); 159 } 160 } 161 if (page_height > 0) 162 pdf->page_size.v = page_height; 163 else { 164 switch (page_direction) { 165 case dir_TLT: 166 case dir_TRT: 167 pdf->page_size.v = height(p) + depth(p) + 2 * page_top_offset; 168 break; 169 case dir_LTL: 170 case dir_RTT: 171 pdf->page_size.v = width(p) + 2 * page_top_offset; 172 break; 173 default: 174 assert(0); 175 } 176 } 177 178 /* Think in upright page/paper coordinates (page origin = lower left edge). 179 First preset |refpoint.pos| to the DVI origin (near upper left page edge). */ 180 181 switch (pdf->o_mode) { 182 case OMODE_DVI: 183 refpoint.pos.h = one_true_inch; 184 refpoint.pos.v = pdf->page_size.v - one_true_inch; 185 dvi = refpoint.pos; 186 break; 187 case OMODE_PDF: 188 case OMODE_LUA: 189 refpoint.pos.h = pdf_h_origin; 190 refpoint.pos.v = pdf->page_size.v - pdf_v_origin; 191 break; 192 default: 193 assert(0); 194 } 195 196 /* Then shift |refpoint.pos| of the DVI origin depending on the 197 |page_direction| within the upright (TLT) page coordinate system */ 198 199 switch (page_direction) { 200 case dir_TLT: 201 case dir_LTL: 202 refpoint.pos.h += h_offset; 203 refpoint.pos.v -= v_offset; 204 break; 205 case dir_TRT: 206 case dir_RTT: 207 refpoint.pos.h += 208 pdf->page_size.h - page_right_offset - one_true_inch; 209 refpoint.pos.v -= v_offset; 210 break; 211 default: 212 assert(0); 213 } 214 215 /* Then switch to page box coordinate system; do |height(p)| movement, 216 to get the location of the box origin. */ 217 218 pdf->posstruct->dir = page_direction; 219 cur.h = 0; 220 cur.v = height(p); 221 synch_pos_with_cur(pdf->posstruct, &refpoint, cur); 222 } else { /* shipping a /Form */ 223 assert(pdf->o_mode == OMODE_PDF); 224 pdf->posstruct->dir = box_dir(p); 225 switch (pdf->posstruct->dir) { 226 case dir_TLT: 227 case dir_TRT: 228 pdf->page_size.h = width(p); 229 pdf->page_size.v = height(p) + depth(p); 230 break; 231 case dir_LTL: 232 case dir_RTT: 233 pdf->page_size.h = height(p) + depth(p); 234 pdf->page_size.v = width(p); 235 break; 236 default: 237 assert(0); 238 } 239 switch (pdf->posstruct->dir) { 240 case dir_TLT: 241 pdf->posstruct->pos.h = 0; 242 pdf->posstruct->pos.v = depth(p); 243 break; 244 case dir_TRT: 245 pdf->posstruct->pos.h = width(p); 246 pdf->posstruct->pos.v = depth(p); 247 break; 248 case dir_LTL: 249 pdf->posstruct->pos.h = height(p); 250 pdf->posstruct->pos.v = width(p); 251 break; 252 case dir_RTT: 253 pdf->posstruct->pos.h = depth(p); 254 pdf->posstruct->pos.v = width(p); 255 break; 256 default: 257 assert(0); 258 } 259 } 260 261 /* Now we are at the point on the page where the origin of the page box should go. */ 262 263 shipbox_refpos = pdf->posstruct->pos; /* for \.{\\gleaders} */ 264 265 switch (pdf->o_mode) { 266 case OMODE_DVI: 267 assert(shipping_mode == SHIPPING_PAGE); 268 dvi_begin_page(pdf); 269 break; 270 case OMODE_PDF: 271 pdf_begin_page(pdf); 272 break; 273 case OMODE_LUA: 274 assert(shipping_mode == SHIPPING_PAGE); 275 lua_begin_page(pdf); 276 break; 277 default: 278 assert(0); 279 } 280 281 switch (type(p)) { 282 case vlist_node: 283 vlist_out(pdf, p); 284 break; 285 case hlist_node: 286 hlist_out(pdf, p); 287 break; 288 default: 289 assert(0); 290 } 291 292 if (shipping_mode == SHIPPING_PAGE) 293 total_pages++; 294 cur_s = -1; 295 296 /* Finish shipping */ 297 298 switch (pdf->o_mode) { 299 case OMODE_DVI: 300 dvi_end_page(pdf); 301 break; 302 case OMODE_PDF: 303 pdf_end_page(pdf); 304 break; 305 case OMODE_LUA: 306 lua_end_page(pdf); 307 break; 308 default: 309 assert(0); 310 } 311 312 DONE: 313 if ((tracing_output <= 0) && (post_callback_id == 0) 314 && shipping_mode == SHIPPING_PAGE) { 315 print_char(']'); 316 update_terminal(); 317 } 318 dead_cycles = 0; 319 /* Flush the box from memory, showing statistics if requested */ 320 if ((tracing_stats > 1) && (pre_callback_id == 0)) { 321 tprint_nl("Memory usage before: "); 322 print_int(var_used); 323 print_char('&'); 324 print_int(dyn_used); 325 print_char(';'); 326 } 327 flush_node_list(p); 328 if ((tracing_stats > 1) && (post_callback_id == 0)) { 329 tprint(" after: "); 330 print_int(var_used); 331 print_char('&'); 332 print_int(dyn_used); 333 print_ln(); 334 } 335 if (shipping_mode == SHIPPING_PAGE && (post_callback_id > 0)) 336 (void) run_callback(post_callback_id, "->"); 337 338 /* Finish sheet {\sl Sync\TeX} information record */ 339 if (int_par(synctex_code)) 340 synctexteehs(); 341 342 global_shipping_mode = NOT_SHIPPING; 343} 344