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
/>.
24 @ Threads are handled in similar way as link annotations
26 void append_bead
(PDF pdf
, halfword p
)
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
)));
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
);
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
);
56 void do_thread
(PDF pdf
, halfword p
, halfword parent_box
, scaledpos cur
)
59 if
((type
(p
) == hlist_node
) && (subtype(p) == pdf_start_thread_node))
60 normal_error
("pdf backend", "'startthread' ended up in hlist");
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
);
82 void append_thread
(PDF pdf
, halfword parent_box
, scaledpos cur
)
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;
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
);
102 pdf-
>last_thread
= p
;
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
) {
117 pdf_ann_bottom
(pdf-
>last_thread
) = pos.v
- pdf_thread_margin
;
120 pdf_ann_right
(pdf-
>last_thread
) = pos.h
+ pdf_thread_margin
;
123 pdf_ann_left
(pdf-
>last_thread
) = pos.h
- pdf_thread_margin
;
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");
140 if
(obj_info
(pdf
, t
) < 0)
141 pdf_print
(pdf
, -obj_info
(pdf
, t
));
143 pdf_print_int
(pdf
, obj_info
(pdf
, t
));
147 void pdf_fix_thread
(PDF pdf
, int t
)
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
);
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
);
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
);
167 pdf_add_bp
(pdf
, page_width_par
);
168 pdf_add_bp
(pdf
, page_height_par
);
172 pdf_begin_obj
(pdf
, t
, OBJSTM_ALWAYS
);
174 pdf_add_name
(pdf
, "I");
176 thread_title
(pdf
, t
);
178 pdf_dict_add_ref
(pdf
, "F", a
);
183 void out_thread
(PDF pdf
, int t
)
187 if
(obj_thread_first
(pdf
, t
) == 0) {
188 pdf_fix_thread
(pdf
, t
);
191 pdf_begin_obj
(pdf
, t
, OBJSTM_ALWAYS
);
193 a
= obj_thread_first
(pdf
, t
);
197 if
(obj_bead_attr
(pdf
, a
) != 0)
198 last_attr
= obj_bead_attr
(pdf
, a
);
199 a
= obj_bead_next
(pdf
, a
);
201 if
(last_attr
!= 0) {
202 pdf_print_ln
(pdf
, last_attr
);
204 pdf_add_name
(pdf
, "I");
206 thread_title
(pdf
, t
);
209 pdf_dict_add_ref
(pdf
, "F", a
);
213 pdf_begin_obj
(pdf
, a
, OBJSTM_ALWAYS
);
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
));
223 a
= obj_bead_next
(pdf
, a
);
228 void scan_thread_id
(void
)
230 if
(scan_keyword
("num")) {
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);
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
);
255 void print_bead_rectangles
(PDF pdf
)
260 if
((k
= get_page_resources_list
(pdf
, obj_type_bead
)) != 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
)
271 set_obj_bead_rect
(pdf
, k-
>info
, l
); /* rewrite |obj_bead_data|
*/