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
/>.
25 #define page_width dimen_par
(page_width_code
)
26 #define page_height dimen_par
(page_height_code
)
28 @ Threads are handled in similar way as link annotations
30 void append_bead
(PDF pdf
, halfword p
)
33 if
(global_shipping_mode
== SHIPPING_FORM
)
34 normal_error
("pdf backend", "threads cannot be inside an xform");
35 t
= pdf_get_obj
(pdf
, obj_type_thread
, pdf_thread_id
(p
), pdf_thread_named_id
(p
));
36 b
= pdf_create_obj
(pdf
, obj_type_others
, 0);
37 obj_bead_ptr
(pdf
, b
) = pdf_get_mem
(pdf
, pdfmem_bead_size
);
38 set_obj_bead_page
(pdf
, b
, pdf-
>last_page
);
39 set_obj_bead_data
(pdf
, b
, p
);
40 if
(pdf_thread_attr
(p
) != null
)
41 set_obj_bead_attr
(pdf
, b
, tokens_to_string
(pdf_thread_attr
(p
)));
43 set_obj_bead_attr
(pdf
, b
, 0);
44 if
(obj_thread_first
(pdf
, t
) == 0) {
45 obj_thread_first
(pdf
, t
) = b
;
46 set_obj_bead_next
(pdf
, b
, b
);
47 set_obj_bead_prev
(pdf
, b
, b
);
49 a
= obj_thread_first
(pdf
, t
);
50 c
= obj_bead_prev
(pdf
, a
);
51 set_obj_bead_prev
(pdf
, b
, c
);
52 set_obj_bead_next
(pdf
, b
, a
);
53 set_obj_bead_prev
(pdf
, a
, b
);
54 set_obj_bead_next
(pdf
, c
, b
);
56 addto_page_resources
(pdf
, obj_type_bead
, b
);
60 void do_thread
(PDF pdf
, halfword p
, halfword parent_box
, scaledpos cur
)
63 if
((type
(p
) == hlist_node
) && (subtype(p) == pdf_start_thread_node))
64 normal_error
("pdf backend", "'startthread' ended up in hlist");
67 if
(subtype
(p
) == pdf_start_thread_node
) {
68 pdf-
>thread.wd
= width
(p
);
69 pdf-
>thread.ht
= height
(p
);
70 pdf-
>thread.dp
= depth
(p
);
71 pdf-
>last_thread_id
= pdf_thread_id
(p
);
72 pdf-
>last_thread_named_id
= (pdf_thread_named_id
(p
) > 0);
73 if
(pdf-
>last_thread_named_id
)
74 add_token_ref
(pdf_thread_id
(p
));
75 pdf-
>thread_level
= cur_s
;
77 alt_rule.wd
= width
(p
);
78 alt_rule.ht
= height
(p
);
79 alt_rule.dp
= depth
(p
);
80 set_rect_dimens
(pdf
, p
, parent_box
, cur
, alt_rule
, pdf_thread_margin
);
86 void append_thread
(PDF pdf
, halfword parent_box
, scaledpos cur
)
89 halfword p
= new_node
(whatsit_node
, pdf_thread_data_node
);
90 width
(p
) = pdf-
>thread.wd
;
91 height
(p
) = pdf-
>thread.ht
;
92 depth
(p
) = pdf-
>thread.dp
;
93 pdf_thread_attr
(p
) = null
;
94 pdf_thread_id
(p
) = pdf-
>last_thread_id
;
95 if
(pdf-
>last_thread_named_id
) {
96 add_token_ref
(pdf_thread_id
(p
));
97 pdf_thread_named_id
(p
) = 1;
99 pdf_thread_named_id
(p
) = 0;
101 alt_rule.wd
= width
(p
);
102 alt_rule.ht
= height
(p
);
103 alt_rule.dp
= depth
(p
);
104 set_rect_dimens
(pdf
, p
, parent_box
, cur
, alt_rule
, pdf_thread_margin
);
106 pdf-
>last_thread
= p
;
110 void end_thread
(PDF pdf
, halfword p
)
112 scaledpos pos
= pdf-
>posstruct-
>pos
;
113 if
(type
(p
) == hlist_node
)
114 normal_error
("pdf backend", "'endthread' ended up in hlist");
115 if
(pdf-
>thread_level
!= cur_s
)
116 normal_error
("pdf backend", "'endthread' ended up in different nesting level than 'startthread'");
117 if
(is_running
(pdf-
>thread.dp
) && (pdf->last_thread != null)) {
118 switch
(pdf-
>posstruct-
>dir
) {
121 pdf_ann_bottom
(pdf-
>last_thread
) = pos.v
- pdf_thread_margin
;
124 pdf_ann_right
(pdf-
>last_thread
) = pos.h
+ pdf_thread_margin
;
127 pdf_ann_left
(pdf-
>last_thread
) = pos.h
- pdf_thread_margin
;
130 formatted_warning
("pdf backend","forcing bad dir %i to TLT in end tread",pdf-
>posstruct-
>dir
);
133 if
(pdf-
>last_thread_named_id
)
134 delete_token_ref
(pdf-
>last_thread_id
);
135 pdf-
>last_thread
= null
;
138 @ The following function are needed for outputing article thread.
140 void thread_title
(PDF pdf
, int t
)
142 pdf_add_name
(pdf
, "Title");
144 if
(obj_info
(pdf
, t
) < 0)
145 pdf_print
(pdf
, -obj_info
(pdf
, t
));
147 pdf_print_int
(pdf
, obj_info
(pdf
, t
));
151 void pdf_fix_thread
(PDF pdf
, int t
)
154 if
(obj_info
(pdf
, t
) < 0) {
155 char
*ss
= makecstring
(-obj_info
(pdf
, t
));
156 formatted_warning
("pdf backend", "unknown thread destination name '%s'",ss
);
158 formatted_warning
("pdf backend", "unknown thread destination num '%d'",obj_info
(pdf
, t
));
160 a
= pdf_create_obj
(pdf
, obj_type_others
, 0);
161 pdf_begin_obj
(pdf
, a
, OBJSTM_ALWAYS
);
163 pdf_dict_add_ref
(pdf
, "T", t
);
164 pdf_dict_add_ref
(pdf
, "V", a
);
165 pdf_dict_add_ref
(pdf
, "N", a
);
166 pdf_dict_add_ref
(pdf
, "P", pdf-
>last_page
);
167 pdf_add_name
(pdf
, "R");
168 pdf_begin_array
(pdf
);
171 pdf_add_bp
(pdf
, page_width
);
172 pdf_add_bp
(pdf
, page_height
);
176 pdf_begin_obj
(pdf
, t
, OBJSTM_ALWAYS
);
178 pdf_add_name
(pdf
, "I");
180 thread_title
(pdf
, t
);
182 pdf_dict_add_ref
(pdf
, "F", a
);
187 void out_thread
(PDF pdf
, int t
)
191 if
(obj_thread_first
(pdf
, t
) == 0) {
192 pdf_fix_thread
(pdf
, t
);
195 pdf_begin_obj
(pdf
, t
, OBJSTM_ALWAYS
);
197 a
= obj_thread_first
(pdf
, t
);
201 if
(obj_bead_attr
(pdf
, a
) != 0)
202 last_attr
= obj_bead_attr
(pdf
, a
);
203 a
= obj_bead_next
(pdf
, a
);
205 if
(last_attr
!= 0) {
206 pdf_print_ln
(pdf
, last_attr
);
208 pdf_add_name
(pdf
, "I");
210 thread_title
(pdf
, t
);
213 pdf_dict_add_ref
(pdf
, "F", a
);
217 pdf_begin_obj
(pdf
, a
, OBJSTM_ALWAYS
);
220 pdf_dict_add_ref
(pdf
, "T", t
);
221 pdf_dict_add_ref
(pdf
, "V", obj_bead_prev
(pdf
, a
));
222 pdf_dict_add_ref
(pdf
, "N", obj_bead_next
(pdf
, a
));
223 pdf_dict_add_ref
(pdf
, "P", obj_bead_page
(pdf
, a
));
224 pdf_dict_add_ref
(pdf
, "R", obj_bead_rect
(pdf
, a
));
227 a
= obj_bead_next
(pdf
, a
);
232 void scan_thread_id
(void
)
234 if
(scan_keyword
("num")) {
237 normal_error
("pdf backend", "num identifier must be positive");
238 if
(cur_val
> max_halfword
)
239 normal_error
("pdf backend", "number too big");
240 set_pdf_thread_id
(cur_list.tail_field
, cur_val
);
241 set_pdf_thread_named_id
(cur_list.tail_field
, 0);
242 } else if
(scan_keyword
("name")) {
243 scan_toks
(false
, true
);
244 set_pdf_thread_id
(cur_list.tail_field
, def_ref
);
245 set_pdf_thread_named_id
(cur_list.tail_field
, 1);
247 normal_error
("pdf backend", "identifier type missing");
251 void check_running_thread
(PDF pdf
, halfword this_box
, scaledpos cur
)
253 if
((pdf-
>last_thread
!= null
) && is_running(pdf->thread.dp)
254 && (pdf->thread_level == cur_s))
255 append_thread
(pdf
, this_box
, cur
);
259 void print_bead_rectangles
(PDF pdf
)
264 if
((k
= get_page_resources_list
(pdf
, obj_type_bead
)) != NULL) {
266 l
= pdf_create_obj
(pdf
, obj_type_others
, 0);
267 pdf_begin_obj
(pdf
, l
, OBJSTM_ALWAYS
);
268 pdf_begin_array
(pdf
);
269 i
= obj_bead_data
(pdf
, k-
>info
); /* pointer to a whatsit or whatsit-like node
*/
270 pdf_add_rect_spec
(pdf
, i
);
271 if
(subtype
(i
) == pdf_thread_data_node
)
275 set_obj_bead_rect
(pdf
, k-
>info
, l
); /* rewrite |obj_bead_data|
*/