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