3 % Copyright
2009-2011 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 @ Data structure of outlines
; it's not able to write out outline entries before
25 all outline entries are defined
, so memory allocated for outline entries can't
26 not be deallocated and will stay in memory. For this reason we will store data of
27 outline entries in |pdf-
>mem| instead of |mem|
30 #define pdfmem_outline_size
8 /* size of memory in |pdf-
>mem| which |obj_outline_ptr| points to
*/
32 #define obj_outline_count obj_info
/* count of all opened children
*/
33 #define obj_outline_ptr obj_aux
/* pointer to |pdf-
>mem|
*/
35 #define obj_outline_title
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
)]
36 #define obj_outline_parent
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 1]
37 #define obj_outline_prev
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 2]
38 #define obj_outline_next
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 3]
39 #define obj_outline_first
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 4]
40 #define obj_outline_last
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 5]
41 #define obj_outline_action_objnum
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 6] /* object number of action
*/
42 #define obj_outline_attr
(pdf
,A
) pdf-
>mem
[obj_outline_ptr
(pdf
,A
) + 7]
44 #define set_obj_outline_count
(pdf
,A
,B
) obj_outline_count
(pdf
,A
)=B
45 #define set_obj_outline_ptr
(pdf
,A
,B
) obj_outline_ptr
(pdf
,A
)=B
46 #define set_obj_outline_action_objnum
(pdf
,A
,B
) obj_outline_action_objnum
(pdf
,A
)=B
47 #define set_obj_outline_title
(pdf
,A
,B
) obj_outline_title
(pdf
,A
)=B
48 #define set_obj_outline_prev
(pdf
,A
,B
) obj_outline_prev
(pdf
,A
)=B
49 #define set_obj_outline_next
(pdf
,A
,B
) obj_outline_next
(pdf
,A
)=B
50 #define set_obj_outline_first
(pdf
,A
,B
) obj_outline_first
(pdf
,A
)=B
51 #define set_obj_outline_last
(pdf
,A
,B
) obj_outline_last
(pdf
,A
)=B
52 #define set_obj_outline_parent
(pdf
,A
,B
) obj_outline_parent
(pdf
,A
)=B
53 #define set_obj_outline_attr
(pdf
,A
,B
) obj_outline_attr
(pdf
,A
)=B
56 static int open_subentries
(PDF pdf
, halfword p
)
60 if
(obj_outline_first
(pdf
, p
) != 0) {
61 l
= obj_outline_first
(pdf
, p
);
64 c
= open_subentries
(pdf
, l
);
65 if
(obj_outline_count
(pdf
, l
) > 0)
67 obj_outline_parent
(pdf
, l
) = p
;
68 r
= obj_outline_next
(pdf
, l
);
70 obj_outline_last
(pdf
, p
) = l
;
74 if
(obj_outline_count
(pdf
, p
) > 0)
75 obj_outline_count
(pdf
, p
) = k
;
77 obj_outline_count
(pdf
, p
) = -k
;
81 @ return number of outline entries in the same level with |p|
84 static int outline_list_count
(PDF pdf
, pointer p
)
87 while
(obj_outline_prev
(pdf
, p
) != 0) {
89 p
= obj_outline_prev
(pdf
, p
);
95 void scan_pdfoutline
(PDF pdf
)
101 if
(scan_keyword
("attr")) {
102 scan_toks
(false
, true
);
107 if
(scan_keyword
("useobjnum")) {
111 p
= scan_action
(pdf
);
113 if
(scan_keyword
("count")) {
119 scan_toks
(false
, true
);
122 j
= pdf_create_obj
(pdf
, obj_type_others
, 0);
123 pdf_begin_obj
(pdf
, j
, OBJSTM_ALWAYS
);
124 write_action
(pdf
, p
);
126 delete_action_ref
(p
);
128 k
= pdf_create_obj
(pdf
, obj_type_outline
, 0);
129 set_obj_outline_ptr
(pdf
, k
, pdf_get_mem
(pdf
, pdfmem_outline_size
));
130 set_obj_outline_action_objnum
(pdf
, k
, j
);
131 set_obj_outline_count
(pdf
, k
, i
);
132 l
= pdf_create_obj
(pdf
, obj_type_others
, 0);
133 pdf_begin_obj
(pdf
, l
, OBJSTM_ALWAYS
);
135 char
*s
= tokenlist_to_cstring
(q
, true
, NULL);
136 pdf_print_str_ln
(pdf
, s
);
141 set_obj_outline_title
(pdf
, k
, l
);
142 set_obj_outline_prev
(pdf
, k
, 0);
143 set_obj_outline_next
(pdf
, k
, 0);
144 set_obj_outline_first
(pdf
, k
, 0);
145 set_obj_outline_last
(pdf
, k
, 0);
146 set_obj_outline_parent
(pdf
, k
, pdf-
>parent_outline
);
147 set_obj_outline_attr
(pdf
, k
, r
);
148 if
(pdf-
>first_outline
== 0)
149 pdf-
>first_outline
= k
;
150 if
(pdf-
>last_outline
== 0) {
151 if
(pdf-
>parent_outline
!= 0)
152 set_obj_outline_first
(pdf
, pdf-
>parent_outline
, k
);
154 set_obj_outline_next
(pdf
, pdf-
>last_outline
, k
);
155 set_obj_outline_prev
(pdf
, k
, pdf-
>last_outline
);
157 pdf-
>last_outline
= k
;
158 if
(obj_outline_count
(pdf
, k
) != 0) {
159 pdf-
>parent_outline
= k
;
160 pdf-
>last_outline
= 0;
161 } else if
((pdf-
>parent_outline
!= 0) &&
162 (outline_list_count
(pdf
, k
) ==
163 abs
(obj_outline_count
(pdf
, pdf-
>parent_outline
)))) {
164 j
= pdf-
>last_outline
;
166 set_obj_outline_last
(pdf
, pdf-
>parent_outline
, j
);
167 j
= pdf-
>parent_outline
;
168 pdf-
>parent_outline
= obj_outline_parent
(pdf
, pdf-
>parent_outline
);
169 } while
(!((pdf-
>parent_outline
== 0) ||
170 (outline_list_count
(pdf
, j
) <
171 abs
(obj_outline_count
(pdf
, pdf-
>parent_outline
)))));
172 if
(pdf-
>parent_outline
== 0)
173 pdf-
>last_outline
= pdf-
>first_outline
;
175 pdf-
>last_outline
= obj_outline_first
(pdf
, pdf-
>parent_outline
);
176 while
(obj_outline_next
(pdf
, pdf-
>last_outline
) != 0)
177 pdf-
>last_outline
= obj_outline_next
(pdf
, pdf-
>last_outline
);
181 @ In the end we must flush PDF objects that cannot be written out immediately
182 after shipping out pages.
185 int print_outlines
(PDF pdf
)
189 if
(pdf-
>first_outline
!= 0) {
190 outlines
= pdf_create_obj
(pdf
, obj_type_others
, 0);
191 l
= pdf-
>first_outline
;
195 a
= open_subentries
(pdf
, l
);
196 if
(obj_outline_count
(pdf
, l
) > 0)
198 set_obj_outline_parent
(pdf
, l
, pdf-
>obj_ptr
);
199 l
= obj_outline_next
(pdf
, l
);
201 pdf_begin_obj
(pdf
, outlines
, OBJSTM_ALWAYS
);
203 pdf_dict_add_name
(pdf
, "Type", "Outlines");
204 pdf_dict_add_ref
(pdf
, "First", pdf-
>first_outline
);
205 pdf_dict_add_ref
(pdf
, "Last", pdf-
>last_outline
);
206 pdf_dict_add_int
(pdf
, "Count", k
);
209 /* Output PDF outline entries
*/
211 k
= pdf-
>head_tab
[obj_type_outline
];
213 if
(obj_outline_parent
(pdf
, k
) == pdf-
>parent_outline
) {
214 if
(obj_outline_prev
(pdf
, k
) == 0)
215 pdf-
>first_outline
= k
;
216 if
(obj_outline_next
(pdf
, k
) == 0)
217 pdf-
>last_outline
= k
;
219 pdf_begin_obj
(pdf
, k
, OBJSTM_ALWAYS
);
221 pdf_dict_add_ref
(pdf
, "Title", obj_outline_title
(pdf
, k
));
222 pdf_dict_add_ref
(pdf
, "A", obj_outline_action_objnum
(pdf
, k
));
223 if
(obj_outline_parent
(pdf
, k
) != 0)
224 pdf_dict_add_ref
(pdf
, "Parent", obj_outline_parent
(pdf
, k
));
225 if
(obj_outline_prev
(pdf
, k
) != 0)
226 pdf_dict_add_ref
(pdf
, "Prev", obj_outline_prev
(pdf
, k
));
227 if
(obj_outline_next
(pdf
, k
) != 0)
228 pdf_dict_add_ref
(pdf
, "Next", obj_outline_next
(pdf
, k
));
229 if
(obj_outline_first
(pdf
, k
) != 0)
230 pdf_dict_add_ref
(pdf
, "First", obj_outline_first
(pdf
, k
));
231 if
(obj_outline_last
(pdf
, k
) != 0)
232 pdf_dict_add_ref
(pdf
, "Last", obj_outline_last
(pdf
, k
));
233 if
(obj_outline_count
(pdf
, k
) != 0)
234 pdf_dict_add_int
(pdf
, "Count", obj_outline_count
(pdf
, k
));
235 if
(obj_outline_attr
(pdf
, k
) != 0) {
237 pdf_print_toks
(pdf
, obj_outline_attr
(pdf
, k
));
239 delete_token_ref
(obj_outline_attr
(pdf
, k
));
240 set_obj_outline_attr
(pdf
, k
, null
);
244 k
= obj_link
(pdf
, k
);