fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfthread.w
blob6b3dd4b943292e8c23c260bb2e40cedca0b0a7cf
1 % pdfthread.w
3 % Copyright 2009-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 @ Threads are handled in similar way as link annotations
26 void append_bead(PDF pdf, halfword p)
28 int a, b, c, t;
29 if (global_shipping_mode == SHIPPING_FORM)
30 normal_error("pdf backend", "threads cannot be inside an xform");
31 t = pdf_get_obj(pdf, obj_type_thread, pdf_thread_id(p), pdf_thread_named_id(p));
32 b = pdf_create_obj(pdf, obj_type_others, 0);
33 obj_bead_ptr(pdf, b) = pdf_get_mem(pdf, pdfmem_bead_size);
34 set_obj_bead_page(pdf, b, pdf->last_page);
35 set_obj_bead_data(pdf, b, p);
36 if (pdf_thread_attr(p) != null)
37 set_obj_bead_attr(pdf, b, tokens_to_string(pdf_thread_attr(p)));
38 else
39 set_obj_bead_attr(pdf, b, 0);
40 if (obj_thread_first(pdf, t) == 0) {
41 obj_thread_first(pdf, t) = b;
42 set_obj_bead_next(pdf, b, b);
43 set_obj_bead_prev(pdf, b, b);
44 } else {
45 a = obj_thread_first(pdf, t);
46 c = obj_bead_prev(pdf, a);
47 set_obj_bead_prev(pdf, b, c);
48 set_obj_bead_next(pdf, b, a);
49 set_obj_bead_prev(pdf, a, b);
50 set_obj_bead_next(pdf, c, b);
52 addto_page_resources(pdf, obj_type_bead, b);
55 @ @c
56 void do_thread(PDF pdf, halfword p, halfword parent_box, scaledpos cur)
58 scaled_whd alt_rule;
59 if ((type(p) == hlist_node) && (subtype(p) == pdf_start_thread_node))
60 normal_error("pdf backend", "'startthread' ended up in hlist");
61 if (doing_leaders)
62 return;
63 if (subtype(p) == pdf_start_thread_node) {
64 pdf->thread.wd = width(p);
65 pdf->thread.ht = height(p);
66 pdf->thread.dp = depth(p);
67 pdf->last_thread_id = pdf_thread_id(p);
68 pdf->last_thread_named_id = (pdf_thread_named_id(p) > 0);
69 if (pdf->last_thread_named_id)
70 add_token_ref(pdf_thread_id(p));
71 pdf->thread_level = cur_s;
73 alt_rule.wd = width(p);
74 alt_rule.ht = height(p);
75 alt_rule.dp = depth(p);
76 set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_thread_margin);
77 append_bead(pdf, p);
78 pdf->last_thread = p;
81 @ @c
82 void append_thread(PDF pdf, halfword parent_box, scaledpos cur)
84 scaled_whd alt_rule;
85 halfword p = new_node(whatsit_node, pdf_thread_data_node);
86 width(p) = pdf->thread.wd;
87 height(p) = pdf->thread.ht;
88 depth(p) = pdf->thread.dp;
89 pdf_thread_attr(p) = null;
90 pdf_thread_id(p) = pdf->last_thread_id;
91 if (pdf->last_thread_named_id) {
92 add_token_ref(pdf_thread_id(p));
93 pdf_thread_named_id(p) = 1;
94 } else {
95 pdf_thread_named_id(p) = 0;
97 alt_rule.wd = width(p);
98 alt_rule.ht = height(p);
99 alt_rule.dp = depth(p);
100 set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_thread_margin);
101 append_bead(pdf, p);
102 pdf->last_thread = p;
105 @ @c
106 void end_thread(PDF pdf, halfword p)
108 scaledpos pos = pdf->posstruct->pos;
109 if (type(p) == hlist_node)
110 normal_error("pdf backend", "'endthread' ended up in hlist");
111 if (pdf->thread_level != cur_s)
112 normal_error("pdf backend", "'endthread' ended up in different nesting level than 'startthread'");
113 if (is_running(pdf->thread.dp) && (pdf->last_thread != null)) {
114 switch (pdf->posstruct->dir) {
115 case dir_TLT:
116 case dir_TRT:
117 pdf_ann_bottom(pdf->last_thread) = pos.v - pdf_thread_margin;
118 break;
119 case dir_LTL:
120 pdf_ann_right(pdf->last_thread) = pos.h + pdf_thread_margin;
121 break;
122 case dir_RTT:
123 pdf_ann_left(pdf->last_thread) = pos.h - pdf_thread_margin;
124 break;
125 default:
126 formatted_warning("pdf backend","forcing bad dir %i to TLT in end tread",pdf->posstruct->dir);
129 if (pdf->last_thread_named_id)
130 delete_token_ref(pdf->last_thread_id);
131 pdf->last_thread = null;
134 @ The following function are needed for outputing article thread.
136 void thread_title(PDF pdf, int t)
138 pdf_add_name(pdf, "Title");
139 pdf_out(pdf, '(');
140 if (obj_info(pdf, t) < 0)
141 pdf_print(pdf, -obj_info(pdf, t));
142 else
143 pdf_print_int(pdf, obj_info(pdf, t));
144 pdf_out(pdf, ')');
147 void pdf_fix_thread(PDF pdf, int t)
149 halfword a;
150 if (obj_info(pdf, t) < 0) {
151 char *ss = makecstring(-obj_info(pdf, t));
152 formatted_warning("pdf backend", "unknown thread destination name '%s'",ss);
153 } else {
154 formatted_warning("pdf backend", "unknown thread destination num '%d'",obj_info(pdf, t));
156 a = pdf_create_obj(pdf, obj_type_others, 0);
157 pdf_begin_obj(pdf, a, OBJSTM_ALWAYS);
158 pdf_begin_dict(pdf);
159 pdf_dict_add_ref(pdf, "T", t);
160 pdf_dict_add_ref(pdf, "V", a);
161 pdf_dict_add_ref(pdf, "N", a);
162 pdf_dict_add_ref(pdf, "P", pdf->last_page);
163 pdf_add_name(pdf, "R");
164 pdf_begin_array(pdf);
165 pdf_add_int(pdf, 0);
166 pdf_add_int(pdf, 0);
167 pdf_add_bp(pdf, page_width_par);
168 pdf_add_bp(pdf, page_height_par);
169 pdf_end_array(pdf);
170 pdf_end_dict(pdf);
171 pdf_end_obj(pdf);
172 pdf_begin_obj(pdf, t, OBJSTM_ALWAYS);
173 pdf_begin_dict(pdf);
174 pdf_add_name(pdf, "I");
175 pdf_begin_dict(pdf);
176 thread_title(pdf, t);
177 pdf_end_dict(pdf);
178 pdf_dict_add_ref(pdf, "F", a);
179 pdf_end_dict(pdf);
180 pdf_end_obj(pdf);
183 void out_thread(PDF pdf, int t)
185 halfword a, b;
186 int last_attr;
187 if (obj_thread_first(pdf, t) == 0) {
188 pdf_fix_thread(pdf, t);
189 return;
191 pdf_begin_obj(pdf, t, OBJSTM_ALWAYS);
192 pdf_begin_dict(pdf);
193 a = obj_thread_first(pdf, t);
194 b = a;
195 last_attr = 0;
196 do {
197 if (obj_bead_attr(pdf, a) != 0)
198 last_attr = obj_bead_attr(pdf, a);
199 a = obj_bead_next(pdf, a);
200 } while (a != b);
201 if (last_attr != 0) {
202 pdf_print_ln(pdf, last_attr);
203 } else {
204 pdf_add_name(pdf, "I");
205 pdf_begin_dict(pdf);
206 thread_title(pdf, t);
207 pdf_end_dict(pdf);
209 pdf_dict_add_ref(pdf, "F", a);
210 pdf_end_dict(pdf);
211 pdf_end_obj(pdf);
212 do {
213 pdf_begin_obj(pdf, a, OBJSTM_ALWAYS);
214 pdf_begin_dict(pdf);
215 if (a == b)
216 pdf_dict_add_ref(pdf, "T", t);
217 pdf_dict_add_ref(pdf, "V", obj_bead_prev(pdf, a));
218 pdf_dict_add_ref(pdf, "N", obj_bead_next(pdf, a));
219 pdf_dict_add_ref(pdf, "P", obj_bead_page(pdf, a));
220 pdf_dict_add_ref(pdf, "R", obj_bead_rect(pdf, a));
221 pdf_end_dict(pdf);
222 pdf_end_obj(pdf);
223 a = obj_bead_next(pdf, a);
224 } while (a != b);
227 @ @c
228 void scan_thread_id(void)
230 if (scan_keyword("num")) {
231 scan_int();
232 if (cur_val <= 0)
233 normal_error("pdf backend", "num identifier must be positive");
234 if (cur_val > max_halfword)
235 normal_error("pdf backend", "number too big");
236 set_pdf_thread_id(cur_list.tail_field, cur_val);
237 set_pdf_thread_named_id(cur_list.tail_field, 0);
238 } else if (scan_keyword("name")) {
239 scan_toks(false, true);
240 set_pdf_thread_id(cur_list.tail_field, def_ref);
241 set_pdf_thread_named_id(cur_list.tail_field, 1);
242 } else {
243 normal_error("pdf backend", "identifier type missing");
247 void check_running_thread(PDF pdf, halfword this_box, scaledpos cur)
249 if ((pdf->last_thread != null) && is_running(pdf->thread.dp)
250 && (pdf->thread_level == cur_s))
251 append_thread(pdf, this_box, cur);
254 @ @c
255 void print_bead_rectangles(PDF pdf)
257 halfword i;
258 pdf_object_list *k;
259 int l;
260 if ((k = get_page_resources_list(pdf, obj_type_bead)) != NULL) {
261 while (k != NULL) {
262 l = pdf_create_obj(pdf, obj_type_others, 0);
263 pdf_begin_obj(pdf, l, OBJSTM_ALWAYS);
264 pdf_begin_array(pdf);
265 i = obj_bead_data(pdf, k->info); /* pointer to a whatsit or whatsit-like node */
266 pdf_add_rect_spec(pdf, i);
267 if (subtype(i) == pdf_thread_data_node)
268 flush_node(i);
269 pdf_end_array(pdf);
270 pdf_end_obj(pdf);
271 set_obj_bead_rect(pdf, k->info, l); /* rewrite |obj_bead_data| */
272 k = k->link;